From ca3cde129895ef2c8888782e672184cc8efd79c6 Mon Sep 17 00:00:00 2001 From: Daya Adianto <dayaadianto@cs.ui.ac.id> Date: Sat, 7 Nov 2020 22:21:16 +0700 Subject: [PATCH 01/10] Create API documentation in README.md (#5) --- README.md | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 164 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2546d20..f7199ac 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,167 @@ [](https://gitlab.cs.ui.ac.id/bukan-macan-ternak/liongame-backend/-/commits/master) [](https://gitlab.cs.ui.ac.id/bukan-macan-ternak/liongame-backend/-/commits/master) -TBD. +## Authorization + +The API uses simple authentication by verifying `Authorization` header. The +value must match with `API_KEY` environment variable loaded by the backend. +Every request must contain `Authorization` header and its value. + +Example request: + +```bash +curl "https://example.com/api/logs" \ + -H "Authorization: 00ff11ee22dd" +``` + +## Play Session Logs + +### Append + +Submits a single play session log. + +```endpoint +POST /logs +``` + +Example request: + +```bash +curl -X POST https://liongame.adian.to/api/logs \ + -H "Authorization: {{ API_KEY }}" +``` + +Example request body: + +> Note: `//` comments are embedded for clarity. The JSON schema corresponds to +> the columns in the actual spreadsheet. +> **Do not actually include the comments in the actual JSON!** + +```json +{ + [ + "VSWM try out", // project_name + "Try Out", // organisation_name + "Minggu 1 Jo", // group_name + "1", // participant_case_number + "Par1", // participant_name + "", // participant_symbol + "", // participant_color + "LvTLiO", // participant_token + "", // taak (?) + "5", // #levels + "4", // #items + "IND", // language + "default_theme", // theme + "16", // matrix_size + "", // id + "60", // task_id + "", // participant_id + "0", // level + "1", // item + "1", // question_number + "red", // correct_answer + "8", // correct_matrix_number + "NA", // response + "12", // response_matrix_number (index position in 1-dimensional array representation) + "131037", // response_time (in milliseconds) + "0", // score + "", // created_at (sent from the game) + "", // updated_at (sent from the game) + "", // deleted_at + ] +} +``` + +Example response: + +> `HTTP 200 OK` + +```json +{ + "status": 200, + "data": { + "participant_name": "{{ participant_name }}", + "created_at": "{{ created_at }}", + } +} +``` + +### Batch Append + +Submits a list of play session logs. + +```endpoint +POST /logs/batch +``` + +Example request: + +```bash +curl -X POST https://liongame.adian.to/api/logs/batch \ + -H "Authorization: {{ API_KEY }}" +``` + +Example request body: + +```json +{ + [ + [ + "VSWM try out", "Try Out", "Minggu 1 Jo", "1", "Par1", "", "", "LvTLiO", + "", "5", "4", "IND", "default_theme", "16", "", "60", "", "0", "1", "1", + "red", "8", "NA", "12", "131037", "0", "", "", "" + ], + [ + "VSWM try out", "Try Out", "Minggu 1 Jo", "1", "Par1", "", "", "LvTLiO", + "", "5", "4", "IND", "default_theme", "16", "", "60", "", "0", "1", "2", + "blue", "3", "NA", "3", "62826", "1", "", "", "" + ], + [ + "VSWM try out", "Try Out", "Minggu 1 Jo", "1", "Par1", "", "", "LvTLiO", + "", "5", "4", "IND", "default_theme", "16", "", "60", "", "0", "2", "1", + "red", "9", "NA", "13", "32213", "0", "", "", "" + ] + ] +} +``` + +Example response: + +> HTTP 200 + +```json +{ + "participant_name": "{{ participant_name }}", + "created_at": "{{ created_at }}", // Latest created_at timestamp +} +``` + +## Errors Response + +The possible errors and their example responses are as follows: + +> `HTTP 400 Bad Request` caused by incorrect request body. + +```json +{ + "status": 400 +} +``` + +> `HTTP 403 Forbidden` caused by failed authorization. + +```json +{ + "status": 403 +} +``` + +> `HTTP 503 Service Unavailable` is possible due to connection issues to Google +> Sheets API. + +```json +{ + "status": 503 +} +``` -- GitLab From 7679a84ba155eea2052c684e21c8b9b9588fecac Mon Sep 17 00:00:00 2001 From: Daya Adianto <dayaadianto@cs.ui.ac.id> Date: Sat, 7 Nov 2020 22:21:36 +0700 Subject: [PATCH 02/10] Tidy up files (#5) --- src/.env.example | 2 +- src/App.php | 3 +-- src/index.php | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/.env.example b/src/.env.example index 79d0e6f..e289357 100644 --- a/src/.env.example +++ b/src/.env.example @@ -1,4 +1,4 @@ -API_KEY=sha512(bangtoyib-cepatpulang) +API_KEY=sha256(bangtoyib-cepatpulang) DEBUG=true GOOGLE_APPLICATION_CREDENTIALS=/opt/liongame/service-account.json SPREADSHEET_ID=1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms diff --git a/src/App.php b/src/App.php index 7f698ce..3d7abd9 100644 --- a/src/App.php +++ b/src/App.php @@ -1,5 +1,4 @@ -<?php -declare(strict_types=1); +<?php declare(strict_types=1); namespace addianto\LionGame\Backend; diff --git a/src/index.php b/src/index.php index 6f99f83..fe9090b 100644 --- a/src/index.php +++ b/src/index.php @@ -1,5 +1,4 @@ -<?php -declare(strict_types=1); +<?php declare(strict_types=1); namespace addianto\LionGame\Backend; -- GitLab From a52023a547fb370952f0c1c40fce489e4544ad70 Mon Sep 17 00:00:00 2001 From: Daya Adianto <dayaadianto@cs.ui.ac.id> Date: Sat, 7 Nov 2020 15:35:52 +0000 Subject: [PATCH 03/10] Modify endpoint URL (#5) --- src/App.php | 3 ++- tests/AppTest.php | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/App.php b/src/App.php index 3d7abd9..5509410 100644 --- a/src/App.php +++ b/src/App.php @@ -42,8 +42,9 @@ class App private function setupController(): void { - $this->app->post("/logs", function (Request $request, Response $response, $args) { + $this->app->post("/api/logs", function (Request $request, Response $response, $args) { $response->getBody()->write(json_encode(array( + "status" => 200, "message" => "TODO: Implement me!" ))); return $response; diff --git a/tests/AppTest.php b/tests/AppTest.php index 3fb849c..c8636d0 100644 --- a/tests/AppTest.php +++ b/tests/AppTest.php @@ -38,23 +38,24 @@ class AppTest extends TestCase $this->assertInstanceOf(SlimApp::class, $this->app); } - public function testPOSTLogsShouldResolve(): void + public function testAppendLogShouldResolve() : void { - $request = $this->buildRequest("POST", "/logs"); + $request = $this->buildRequest("POST", "/api/logs"); $response = $this->app->handle($request); $this->assertEquals(200, $response->getStatusCode()); } - public function testPOSTLogsShouldReturnJSON(): void + public function testAppendLogShouldReturnJSON(): void { - $request = $this->buildRequest("POST", "/logs"); + $request = $this->buildRequest("POST", "/api/logs"); $response = $this->app->handle($request); $jsonString = $response->getBody()->__toString(); $json = json_decode($jsonString); $this->assertEquals(self::SUCCESS_JSON_DECODE, json_last_error()); + $this->assertEquals(200, $json->status); } private function buildRequest(string $method, string $path) -- GitLab From 5e3fa79ed8cfa771096d39627cf66c12764b1633 Mon Sep 17 00:00:00 2001 From: Daya Adianto <dayaadianto@cs.ui.ac.id> Date: Sat, 7 Nov 2020 15:39:12 +0000 Subject: [PATCH 04/10] Add tests (#5) --- tests/AppTest.php | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/AppTest.php b/tests/AppTest.php index c8636d0..560fe41 100644 --- a/tests/AppTest.php +++ b/tests/AppTest.php @@ -38,7 +38,7 @@ class AppTest extends TestCase $this->assertInstanceOf(SlimApp::class, $this->app); } - public function testAppendLogShouldResolve() : void + public function testAppendLogShouldResolve(): void { $request = $this->buildRequest("POST", "/api/logs"); $response = $this->app->handle($request); @@ -58,6 +58,26 @@ class AppTest extends TestCase $this->assertEquals(200, $json->status); } + public function testBatchAppendLogShouldResolve(): void + { + $request = $this->buildRequest("POST", "/api/logs/batch"); + $response = $this->app->handle($request); + + $this->assertEquals(200, $response->getStatusCode()); + } + + public function testBatchAppendLogsShouldReturnJSON(): void + { + $request = $this->buildRequest("POST", "/api/logs/batch"); + + $response = $this->app->handle($request); + $jsonString = $response->getBody()->__toString(); + $json = json_decode($jsonString); + + $this->assertEquals(self::SUCCESS_JSON_DECODE, json_last_error()); + $this->assertEquals(200, $json->status); + } + private function buildRequest(string $method, string $path) { return RequestFactory::create() -- GitLab From 8d9fe834b181d35b96ddb07bb705b0967c670624 Mon Sep 17 00:00:00 2001 From: Daya Adianto <dayaadianto@cs.ui.ac.id> Date: Sat, 7 Nov 2020 17:10:29 +0000 Subject: [PATCH 05/10] Implement append log endpoint (#5) --- src/App.php | 72 ++++++++++++++++++++++++--- tests/AppTest.php | 122 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 164 insertions(+), 30 deletions(-) diff --git a/src/App.php b/src/App.php index 5509410..cf06e9c 100644 --- a/src/App.php +++ b/src/App.php @@ -8,9 +8,11 @@ use Slim\Factory\AppFactory; use Slim\App as SlimApp; use addianto\LionGame\Backend\Config\Config; use addianto\LionGame\Backend\Service\SheetsService; +use count; class App { + const VALID_LENGTH = 29; private string $apiKey; private SlimApp $app; private SheetsService $sheets; @@ -37,17 +39,75 @@ class App private function setupMiddleware(): void { + $this->app->addBodyParsingMiddleware(); $this->app->addErrorMiddleware($this->debug, true, true); } private function setupController(): void { - $this->app->post("/api/logs", function (Request $request, Response $response, $args) { - $response->getBody()->write(json_encode(array( - "status" => 200, - "message" => "TODO: Implement me!" - ))); - return $response; + $this->app->post("/api/logs", function (Request $request, Response $response, $args): Response { + if (!self::isAuthorized($request, $this->apiKey)) { + $response + ->withStatus(403) + ->getBody()->write(json_encode(array( + "status" => 403, + ))); + + return $response; + } + + $data = $request->getParsedBody(); + + if (!self::isValidData($data)) { + $response + ->withStatus(400) + ->getBody()->write(json_encode(array( + "status" => 400, + ))); + + return $response; + } + + if ($this->sheets->appendValues( + "'Play Session Analytics (Example)'A:AC", + $data + )) { + $response + ->withStatus(200) + ->getBody()->write(json_encode(array( + "status" => 200, + "data" => array( + "participant_name" => $data[4], + "created_at" => $data[26], + ), + ))); + + return $response; + } else { + $response + ->withStatus(503) + ->getBody()->write(json_encode(array( + "status" => 503, + ))); + + return $response; + } }); } + + private static function isAuthorized(Request $request, string $apiKey): bool + { + if (!$request->hasHeader("Authorization")) { + return false; + } + + $headerValue = $request->getHeader("Authorization"); + + return $headerValue[0] == $apiKey; + } + + private static function isValidData(array $data): bool + { + return count($data) == self::VALID_LENGTH; + } } diff --git a/tests/AppTest.php b/tests/AppTest.php index 560fe41..e17c437 100644 --- a/tests/AppTest.php +++ b/tests/AppTest.php @@ -23,12 +23,14 @@ class AppTest extends TestCase const SUCCESS_JSON_DECODE = 0; private SlimApp $app; + private SheetsService $sheets; protected function setUp(): void { + $this->sheets = $this->createMock(SheetsService::class); $this->app = (new App( self::API_KEY, - $this->createMock(SheetsService::class), + $this->sheets, self::DEBUG ))->get(); } @@ -38,51 +40,123 @@ class AppTest extends TestCase $this->assertInstanceOf(SlimApp::class, $this->app); } - public function testAppendLogShouldResolve(): void + public function testAppendLogShouldReturnJSON(): void { - $request = $this->buildRequest("POST", "/api/logs"); - $response = $this->app->handle($request); + $this->sheets + ->method("appendValues") + ->willReturn(true); + $request = $this->buildRequest( + "POST", + "/api/logs", + self::API_KEY, + $this->getValidRequestBody() + ); + + $json = $this->getJSON($this->app->handle($request)); - $this->assertEquals(200, $response->getStatusCode()); + $this->assertEquals(200, $json->status); } - public function testAppendLogShouldReturnJSON(): void + + public function testBatchAppendLogsShouldReturnJSON(): void { - $request = $this->buildRequest("POST", "/api/logs"); + $request = $this->buildRequest( + "POST", + "/api/logs/batch", + self::API_KEY, + $this->getValidRequestBody() + ); - $response = $this->app->handle($request); - $jsonString = $response->getBody()->__toString(); - $json = json_decode($jsonString); + $json = $this->getJSON($this->app->handle($request)); - $this->assertEquals(self::SUCCESS_JSON_DECODE, json_last_error()); $this->assertEquals(200, $json->status); + $this->assertEquals("Par1", $json->data->participant_name); } - public function testBatchAppendLogShouldResolve(): void + public function testFailedAuthorizationOnAppendLog(): void { - $request = $this->buildRequest("POST", "/api/logs/batch"); - $response = $this->app->handle($request); + $request = $this->buildRequest( + "POST", + "/api/logs", + "a", + $this->getValidRequestBody() + ); + + $json = $this->getJSON($this->app->handle($request)); - $this->assertEquals(200, $response->getStatusCode()); + $this->assertEquals(403, $json->status); } - public function testBatchAppendLogsShouldReturnJSON(): void + public function testInvalidDataOnAppendLog(): void { - $request = $this->buildRequest("POST", "/api/logs/batch"); + $request = $this->buildRequest( + "POST", + "/api/logs", + self::API_KEY, + $this->getInvalidRequestBody() + ); - $response = $this->app->handle($request); - $jsonString = $response->getBody()->__toString(); - $json = json_decode($jsonString); + $json = $this->getJSON($this->app->handle($request)); - $this->assertEquals(self::SUCCESS_JSON_DECODE, json_last_error()); - $this->assertEquals(200, $json->status); + $this->assertEquals(400, $json->status); } - private function buildRequest(string $method, string $path) + public function testGoogleSheetsAPIUnavailableOnAppendLog(): void { + $this->sheets + ->method("appendValues") + ->willReturn(false); + $request = $this->buildRequest( + "POST", + "/api/logs", + self::API_KEY, + $this->getValidRequestBody() + ); + + $json = $this->getJSON($this->app->handle($request)); + + $this->assertEquals(503, $json->status); + } + + private function buildRequest( + string $method, + string $path, + string $authorization, + array $body = [] + ) { return RequestFactory::create() ->createServerRequestFromGlobals() + ->withHeader("Authorization", $authorization) + ->withHeader("Content-Type", "application/json") ->withMethod(strtoupper($method)) - ->withUri(UriFactory::createUri($path)); + ->withUri(UriFactory::createUri($path)) + ->withParsedBody($body); + } + + private function getJSON(Response $response): object + { + $jsonString = $response->getBody()->__toString(); + $json = json_decode($jsonString); + + $this->assertEquals(self::SUCCESS_JSON_DECODE, json_last_error()); + + return $json; + } + + private function getValidRequestBody(): array + { + return [ + "VSWM try out", "Try Out", "Minggu 1 Jo", "1", "Par1", "", "", "LvTLiO", + "", "5", "4", "IND", "default_theme", "16", "", "60", "", "0", "1", "1", + "red", "8", "NA", "12", "131037", "0", "", "", "" + ]; + } + + private function getInvalidRequestBody(): array + { + return [ + "VSWM try out", "Try Out", "Minggu 1 Jo", "1", "Par1", "", "", "LvTLiO", + "", "5", "4", "IND", "default_theme", "16", "", "60", "", "0", "1", "1" + ]; } } -- GitLab From ff4f970989026f6d046bd67c7c5f2b6195d3ff99 Mon Sep 17 00:00:00 2001 From: Daya Adianto <dayaadianto@cs.ui.ac.id> Date: Sat, 7 Nov 2020 17:36:49 +0000 Subject: [PATCH 06/10] Implement batch append log endpoint (#5) --- src/App.php | 68 ++++++++++++++++++++++++++--------- src/service/SheetsService.php | 2 +- tests/AppTest.php | 28 +++++++++++++-- 3 files changed, 79 insertions(+), 19 deletions(-) diff --git a/src/App.php b/src/App.php index cf06e9c..17858cb 100644 --- a/src/App.php +++ b/src/App.php @@ -9,6 +9,7 @@ use Slim\App as SlimApp; use addianto\LionGame\Backend\Config\Config; use addianto\LionGame\Backend\Service\SheetsService; use count; +use json_encode; class App { @@ -47,25 +48,49 @@ class App { $this->app->post("/api/logs", function (Request $request, Response $response, $args): Response { if (!self::isAuthorized($request, $this->apiKey)) { - $response - ->withStatus(403) - ->getBody()->write(json_encode(array( - "status" => 403, - ))); - + self::buildErrorResponse($response, 403); return $response; } $data = $request->getParsedBody(); if (!self::isValidData($data)) { + self::buildErrorResponse($response, 400); + return $response; + } + + if ($this->sheets->appendValues( + "'Play Session Analytics (Example)'A:AC", + array($data) + )) { $response - ->withStatus(400) + ->withStatus(200) ->getBody()->write(json_encode(array( - "status" => 400, + "status" => 200, + "data" => array( + "participant_name" => $data[0][4], + "created_at" => $data[0][26], + ), ))); return $response; + } else { + self::buildErrorResponse($response, 503); + return $response; + } + }); + + $this->app->post("/api/logs/batch", function (Request $request, Response $response, $args): Response { + if (!self::isAuthorized($request, $this->apiKey)) { + self::buildErrorResponse($response, 403); + return $response; + } + + $data = $request->getParsedBody(); + + if (!self::isValidData($data)) { + self::buildErrorResponse($response, 400); + return $response; } if ($this->sheets->appendValues( @@ -77,24 +102,26 @@ class App ->getBody()->write(json_encode(array( "status" => 200, "data" => array( - "participant_name" => $data[4], - "created_at" => $data[26], + "participant_name" => $data[count($data)-1][4], + "created_at" => $data[count($data)-1][26], ), ))); return $response; } else { - $response - ->withStatus(503) - ->getBody()->write(json_encode(array( - "status" => 503, - ))); - + self::buildErrorResponse($response, 503); return $response; } }); } + private static function buildErrorResponse(Response $response, int $code): void + { + $response->withStatus($code)->getBody()->write(json_encode(array( + "status" => $code, + ))); + } + private static function isAuthorized(Request $request, string $apiKey): bool { if (!$request->hasHeader("Authorization")) { @@ -108,6 +135,15 @@ class App private static function isValidData(array $data): bool { + if (is_array($data[0])) { + foreach ($data as $entry) { + if (count($entry) != self::VALID_LENGTH) { + return false; + } + } + return true; + } + return count($data) == self::VALID_LENGTH; } } diff --git a/src/service/SheetsService.php b/src/service/SheetsService.php index 9c6a0c3..1db27f9 100644 --- a/src/service/SheetsService.php +++ b/src/service/SheetsService.php @@ -45,7 +45,7 @@ class SheetsService try { $body = new ValueRange([ "majorDimension" => "ROWS", - "values" => array($values), + "values" => $values, ]); $optionalParameters = array( diff --git a/tests/AppTest.php b/tests/AppTest.php index e17c437..6b8b936 100644 --- a/tests/AppTest.php +++ b/tests/AppTest.php @@ -57,14 +57,20 @@ class AppTest extends TestCase $this->assertEquals(200, $json->status); } - public function testBatchAppendLogsShouldReturnJSON(): void { + $this->sheets + ->method("appendValues") + ->willReturn(true); $request = $this->buildRequest( "POST", "/api/logs/batch", self::API_KEY, - $this->getValidRequestBody() + array( + $this->getValidRequestBody(), + $this->getValidRequestBody(), + $this->getValidRequestBody(), + ) ); $json = $this->getJSON($this->app->handle($request)); @@ -101,6 +107,24 @@ class AppTest extends TestCase $this->assertEquals(400, $json->status); } + public function testInvalidDataOnBatchAppendLog(): void + { + $request = $this->buildRequest( + "POST", + "/api/logs", + self::API_KEY, + array( + $this->getValidRequestBody(), + $this->getInvalidRequestBody(), + $this->getValidRequestBody(), + ) + ); + + $json = $this->getJSON($this->app->handle($request)); + + $this->assertEquals(400, $json->status); + } + public function testGoogleSheetsAPIUnavailableOnAppendLog(): void { $this->sheets -- GitLab From f7cbc664ae3738999eb1591d395d3eba439b47e0 Mon Sep 17 00:00:00 2001 From: Daya Adianto <dayaadianto@cs.ui.ac.id> Date: Sun, 8 Nov 2020 00:41:01 +0700 Subject: [PATCH 07/10] Tidy source code (#5) --- src/service/SheetsService.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/service/SheetsService.php b/src/service/SheetsService.php index 1db27f9..abb256a 100644 --- a/src/service/SheetsService.php +++ b/src/service/SheetsService.php @@ -25,8 +25,7 @@ class SheetsService $values = array(); try { - $response = $this->api - ->spreadsheets_values + $response = $this->api->spreadsheets_values ->get($this->spreadsheetId, $range); $values = $response->getValues(); @@ -53,8 +52,7 @@ class SheetsService "valueInputOption" => "RAW", ); - $response = $this->api - ->spreadsheets_values + $this->api->spreadsheets_values ->append($this->spreadsheetId, $range, $body, $optionalParameters); $isAppended = true; -- GitLab From 3ef82d1be36b854667c548a5b070fbecbd208842 Mon Sep 17 00:00:00 2001 From: Daya Adianto <dayaadianto@cs.ui.ac.id> Date: Sun, 8 Nov 2020 03:06:50 +0700 Subject: [PATCH 08/10] Fix use statements (#5) --- src/index.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/index.php b/src/index.php index fe9090b..884e1b9 100644 --- a/src/index.php +++ b/src/index.php @@ -4,6 +4,8 @@ namespace addianto\LionGame\Backend; use Dotenv\Dotenv; use addianto\LionGame\Backend\App; +use addianto\LionGame\Backend\Config\Config; +use addianto\LionGame\Backend\Service\SheetsService; require __DIR__ . '/../vendor/autoload.php'; -- GitLab From 69afcf480faae63845c0ed4406de1467b94f239e Mon Sep 17 00:00:00 2001 From: Daya Adianto <dayaadianto@cs.ui.ac.id> Date: Sun, 8 Nov 2020 03:07:03 +0700 Subject: [PATCH 09/10] Fix documentation (#5) --- README.md | 96 ++++++++++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index f7199ac..64afc8f 100644 --- a/README.md +++ b/README.md @@ -43,39 +43,37 @@ Example request body: > **Do not actually include the comments in the actual JSON!** ```json -{ - [ - "VSWM try out", // project_name - "Try Out", // organisation_name - "Minggu 1 Jo", // group_name - "1", // participant_case_number - "Par1", // participant_name - "", // participant_symbol - "", // participant_color - "LvTLiO", // participant_token - "", // taak (?) - "5", // #levels - "4", // #items - "IND", // language - "default_theme", // theme - "16", // matrix_size - "", // id - "60", // task_id - "", // participant_id - "0", // level - "1", // item - "1", // question_number - "red", // correct_answer - "8", // correct_matrix_number - "NA", // response - "12", // response_matrix_number (index position in 1-dimensional array representation) - "131037", // response_time (in milliseconds) - "0", // score - "", // created_at (sent from the game) - "", // updated_at (sent from the game) - "", // deleted_at - ] -} +[ + "VSWM try out", // project_name + "Try Out", // organisation_name + "Minggu 1 Jo", // group_name + "1", // participant_case_number + "Par1", // participant_name + "", // participant_symbol + "", // participant_color + "LvTLiO", // participant_token + "", // taak (?) + "5", // #levels + "4", // #items + "IND", // language + "default_theme", // theme + "16", // matrix_size + "", // id + "60", // task_id + "", // participant_id + "0", // level + "1", // item + "1", // question_number + "red", // correct_answer + "8", // correct_matrix_number + "NA", // response + "12", // response_matrix_number (index position in 1-dimensional array representation) + "131037", // response_time (in milliseconds) + "0", // score + "", // created_at (sent from the game) + "", // updated_at (sent from the game) + "", // deleted_at +] ``` Example response: @@ -110,25 +108,23 @@ curl -X POST https://liongame.adian.to/api/logs/batch \ Example request body: ```json -{ +[ + [ + "VSWM try out", "Try Out", "Minggu 1 Jo", "1", "Par1", "", "", "LvTLiO", + "", "5", "4", "IND", "default_theme", "16", "", "60", "", "0", "1", "1", + "red", "8", "NA", "12", "131037", "0", "", "", "" + ], [ - [ - "VSWM try out", "Try Out", "Minggu 1 Jo", "1", "Par1", "", "", "LvTLiO", - "", "5", "4", "IND", "default_theme", "16", "", "60", "", "0", "1", "1", - "red", "8", "NA", "12", "131037", "0", "", "", "" - ], - [ - "VSWM try out", "Try Out", "Minggu 1 Jo", "1", "Par1", "", "", "LvTLiO", - "", "5", "4", "IND", "default_theme", "16", "", "60", "", "0", "1", "2", - "blue", "3", "NA", "3", "62826", "1", "", "", "" - ], - [ - "VSWM try out", "Try Out", "Minggu 1 Jo", "1", "Par1", "", "", "LvTLiO", - "", "5", "4", "IND", "default_theme", "16", "", "60", "", "0", "2", "1", - "red", "9", "NA", "13", "32213", "0", "", "", "" - ] + "VSWM try out", "Try Out", "Minggu 1 Jo", "1", "Par1", "", "", "LvTLiO", + "", "5", "4", "IND", "default_theme", "16", "", "60", "", "0", "1", "2", + "blue", "3", "NA", "3", "62826", "1", "", "", "" + ], + [ + "VSWM try out", "Try Out", "Minggu 1 Jo", "1", "Par1", "", "", "LvTLiO", + "", "5", "4", "IND", "default_theme", "16", "", "60", "", "0", "2", "1", + "red", "9", "NA", "13", "32213", "0", "", "", "" ] -} +] ``` Example response: -- GitLab From 375d278b9b686dfc07ce6f349964bb36251522de Mon Sep 17 00:00:00 2001 From: Daya Adianto <dayaadianto@cs.ui.ac.id> Date: Sun, 8 Nov 2020 03:08:03 +0700 Subject: [PATCH 10/10] Fix sheets range (#5) --- src/App.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/App.php b/src/App.php index 17858cb..575a7c0 100644 --- a/src/App.php +++ b/src/App.php @@ -60,7 +60,7 @@ class App } if ($this->sheets->appendValues( - "'Play Session Analytics (Example)'A:AC", + "'Play Session Analytics (Example)'!A:AC", array($data) )) { $response @@ -94,7 +94,7 @@ class App } if ($this->sheets->appendValues( - "'Play Session Analytics (Example)'A:AC", + "'Play Session Analytics (Example)'!A:AC", $data )) { $response -- GitLab