feat: complete human-vs-ESP32 gameplay and cumulative statistics
This commit is contained in:
+23
-2
@@ -44,6 +44,7 @@ static http_api_t s_api;
|
||||
static sync_service_t s_sync;
|
||||
static uint16_t s_rejected_input;
|
||||
static esp_timer_handle_t s_sync_timer;
|
||||
static esp_timer_handle_t s_bot_timer;
|
||||
#if WIFI_CONFIG_AVAILABLE
|
||||
static esp_timer_handle_t s_reconnect_timer;
|
||||
#endif
|
||||
@@ -110,6 +111,22 @@ static void queue_state_broadcast(void) {
|
||||
if (s_server != NULL && httpd_queue_work(s_server, sync_broadcast_work, NULL) != ESP_OK) ++s_rejected_input;
|
||||
}
|
||||
|
||||
static bool schedule_bot_turn(void *unused, uint32_t delay_ms) {
|
||||
(void)unused;
|
||||
return s_bot_timer != NULL && esp_timer_start_once(s_bot_timer, (uint64_t)delay_ms * 1000U) == ESP_OK;
|
||||
}
|
||||
|
||||
static void bot_turn_work(void *unused) {
|
||||
(void)unused;
|
||||
const uint32_t version_before = s_application.lifecycle.game.state.version;
|
||||
if (application_bot_take_turn(&s_application) && s_application.lifecycle.game.state.version != version_before) queue_state_broadcast();
|
||||
}
|
||||
|
||||
static void bot_timer_callback(void *unused) {
|
||||
(void)unused;
|
||||
if (s_server != NULL && httpd_queue_work(s_server, bot_turn_work, NULL) != ESP_OK) ++s_rejected_input;
|
||||
}
|
||||
|
||||
static void sync_expire_work(void *unused) {
|
||||
(void)unused;
|
||||
int closed[kSessionCapacity] = {0};
|
||||
@@ -162,7 +179,7 @@ static esp_err_t api_handler(httpd_req_t *request) {
|
||||
}
|
||||
const bool target_too_large = request->method == HTTP_GET && httpd_req_get_url_query_len(request) > 128U;
|
||||
if (target_too_large) ++s_rejected_input;
|
||||
if (route == HTTP_API_ROUTE_STATE) {
|
||||
if (route == HTTP_API_ROUTE_STATE || route == HTTP_API_ROUTE_STATISTICS) {
|
||||
const size_t token_length = httpd_req_get_hdr_value_len(request, "X-Session-Token");
|
||||
if (token_length > 0U && token_length < sizeof(token) && httpd_req_get_hdr_value_str(request, "X-Session-Token", token, sizeof(token)) != ESP_OK) token[0] = '\0';
|
||||
else if (token_length >= sizeof(token)) snprintf(token, sizeof(token), "%s", "invalid");
|
||||
@@ -328,7 +345,7 @@ static esp_err_t static_file_handler(httpd_req_t *request) {
|
||||
|
||||
static esp_err_t start_http_server(void) {
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.max_uri_handlers = 15U; config.max_open_sockets = kHttpMaxOpenSockets; config.uri_match_fn = httpd_uri_match_wildcard; config.lru_purge_enable = true;
|
||||
config.max_uri_handlers = 16U; config.max_open_sockets = kHttpMaxOpenSockets; config.uri_match_fn = httpd_uri_match_wildcard; config.lru_purge_enable = true;
|
||||
ESP_RETURN_ON_ERROR(httpd_start(&s_server, &config), kLogTag, "http server start failed");
|
||||
const httpd_uri_t routes[] = {
|
||||
{.uri = "/", .method = HTTP_GET, .handler = root_handler},
|
||||
@@ -342,6 +359,7 @@ static esp_err_t start_http_server(void) {
|
||||
{.uri = "/api/game/rematch", .method = HTTP_POST, .handler = api_handler, .user_ctx = (void *)(uintptr_t)HTTP_API_ROUTE_REMATCH},
|
||||
{.uri = "/api/game/abort", .method = HTTP_POST, .handler = api_handler, .user_ctx = (void *)(uintptr_t)HTTP_API_ROUTE_ABORT},
|
||||
{.uri = "/api/state", .method = HTTP_GET, .handler = api_handler, .user_ctx = (void *)(uintptr_t)HTTP_API_ROUTE_STATE},
|
||||
{.uri = "/api/statistics", .method = HTTP_GET, .handler = api_handler, .user_ctx = (void *)(uintptr_t)HTTP_API_ROUTE_STATISTICS},
|
||||
{.uri = "/ws", .method = HTTP_GET, .handler = websocket_handler, .is_websocket = true},
|
||||
{.uri = "/*", .method = HTTP_GET, .handler = static_file_handler},
|
||||
};
|
||||
@@ -360,6 +378,9 @@ void app_main(void) {
|
||||
if (result == ESP_ERR_NVS_NO_FREE_PAGES || result == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); result = nvs_flash_init(); }
|
||||
ESP_ERROR_CHECK(result); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
application_init(&s_application, (random_source_t){.next_u32 = platform_random, .context = NULL});
|
||||
const esp_timer_create_args_t bot_timer_args = {.callback = bot_timer_callback, .name = "bot_turn"};
|
||||
ESP_ERROR_CHECK(esp_timer_create(&bot_timer_args, &s_bot_timer));
|
||||
application_set_bot_scheduler(&s_application, (scheduler_t){.schedule_after_ms = schedule_bot_turn, .context = NULL});
|
||||
http_api_init(&s_api, &s_application);
|
||||
sync_service_init(&s_sync, &s_application);
|
||||
mount_littlefs();
|
||||
|
||||
Reference in New Issue
Block a user