From 3c0e7590ce18a9c32256b5d7d18c75b3d92cedea Mon Sep 17 00:00:00 2001 From: Sky Johnson Date: Sat, 5 Oct 2024 18:28:04 -0500 Subject: [PATCH] Remove typing, work on stopwatches and debug --- database/live.db | Bin 188416 -> 188416 bytes public/index.php | 8 ++++++ src/auth.php | 9 +++++++ src/bootstrap.php | 10 ++++++- src/components.php | 10 ++++++- src/controllers/char.php | 6 ++--- src/database.php | 33 +++++++++++++---------- src/env.php | 9 ++++++- src/helpers.php | 33 +++++++++++++++++++++-- src/models/char.php | 8 +++--- src/models/items.php | 7 ----- src/render.php | 2 +- src/router.php | 4 +-- templates/components/debug_query_log.php | 8 +++++- templates/components/debug_stopwatch.php | 6 +++++ templates/layouts/basic.php | 8 +++++- 16 files changed, 123 insertions(+), 38 deletions(-) create mode 100644 templates/components/debug_stopwatch.php diff --git a/database/live.db b/database/live.db index cced5b278fbb0b3e1ba83b9061c0034b6c6310c4..dcc54c5420f099ebde312939efcf577de2321cc6 100644 GIT binary patch delta 521 zcmb7=&r2IY6vy9eUeeu!%-3EL!5_qn8d{+ut(Srq&;9`-L@1uBNe>0Fmn3@g;$f^I z7qx-5^dPz>AQ5DfgQZ1_YpK*y>}qWVOF^;pDxGHg50uYg<_*mE^WMwVBDq>*jYnIp zs7LsOSvDXMCoh`Y_koX>q_39EBuHmI!NjiYMBdl)vPm+>#|9 zJ3lQ|X>pt}NG+xhj2$%SQZ}@`uc#Rr1QSs5*d8o>2Gvkm# z%3V#~2nPc~Ft0apVusxfcEz>VUezf@!Z}X#^!up8#w$ES(MP9Dp-^;;1mi84g)PVE zzYWtgLmU+P(9{2K8(sg}2xCX9%Y+LpKgE%j`&%ocLAhgj9)*f$=*4}cP+`wAl4e8% I*)#?J0hHjYsQ>@~ delta 517 zcmb7=!An$O6ve;q&3)sW_jupYMUIMzZAJ$btROc+o7VjW!4%P|nrRV8ZDz)HZd_b- zcpIk%N?M3M--DQ9n3+XUSTseE5%nrFP=cZe!a)2Q{0Caya~Jpg&bft#Q)oD=bhh7d zBZ0T@F@y7%RGaF7I-`!Ogd4e$U#zm5p+vI19?cbu6mc!v z$Io&T{SGn$-!QH1rf?A%{KjXjp@k(Z`NfmqO#XyC#0&XxLkNDH9~-e_z4G*hsjImx z*?1=$R0V$GuRdAVMqlv}ukjFdR8bAOIz4c8Hc1pqNPab&O0^ZaI3*la5m?0*=5bwf z(@^S{+E6uBQ5C;9t+=vy$>_EDT)Bsb%XefSHy68kt9*E1LqkJ>AK1kXzTg91;wc`X zf%^y%YUms|Th=wT5>NMc%ofAfo=T3C*A%9nmV$NySN1p zo_4v0l2 $id, 'char' => $char]); } @@ -88,3 +88,11 @@ function c_form_field($type, $name, $placeholder, $required = false, $autocomple $html .= $errors !== false && !empty($errors[$name]) ? ' class="form control error"' : ' class="form control"'; return $html . " autocomplete=\"$autocomplete\">"; } + +/** + * Render the stopwatch debug component. + */ +function c_debug_stopwatch() +{ + return render('components/debug_stopwatch'); +} diff --git a/src/controllers/char.php b/src/controllers/char.php index c636e1a..b9e5e2e 100644 --- a/src/controllers/char.php +++ b/src/controllers/char.php @@ -5,7 +5,7 @@ */ function char_controller_list_get() { - auth_only(); must_have_character(); + auth_only_and_must_have_character(); $GLOBALS['active_nav_tab'] = 'chars'; echo page('chars/list', ['chars' => char_list(user('id'))]); @@ -16,7 +16,7 @@ function char_controller_list_get() */ function char_controller_list_post() { - auth_only(); must_have_character(); csrf_ensure(); + auth_only_and_must_have_character(); csrf_ensure(); $GLOBALS['active_nav_tab'] = 'chars'; @@ -68,7 +68,7 @@ function char_controller_list_post() */ function char_controller_delete_post() { - auth_only(); must_have_character(); csrf_ensure(); + auth_only_and_must_have_character(); csrf_ensure(); $char_id = (int) ($_POST['char_id'] ?? 0); diff --git a/src/database.php b/src/database.php index d5b5a34..6de165a 100644 --- a/src/database.php +++ b/src/database.php @@ -3,7 +3,7 @@ /** * Open a connection to a database. */ -function db_open($path): SQLite3 +function db_open($path) { $db = new SQLite3($path); @@ -20,7 +20,7 @@ function db_open($path): SQLite3 /** * Return a connection to the auth database. */ -function db_auth(): SQLite3 +function db_auth() { return $GLOBALS['db_auth'] ??= db_open(__DIR__ . '/../database/auth.db'); } @@ -28,7 +28,7 @@ function db_auth(): SQLite3 /** * Return a connection to the live database. */ -function db_live(): SQLite3 +function db_live() { return $GLOBALS['db_live'] ??= db_open(__DIR__ . '/../database/live.db'); } @@ -37,7 +37,7 @@ function db_live(): SQLite3 /** * Return a connection to the fights database. */ -function db_fights(): SQLite3 +function db_fights() { return $GLOBALS['db_fights'] ??= db_open(__DIR__ . '/../database/fights.db'); } @@ -46,7 +46,7 @@ function db_fights(): SQLite3 /** * Return a connection to the blueprints database. */ -function db_blueprints(): SQLite3 +function db_blueprints() { return $GLOBALS['db_blueprints'] ??= db_open(__DIR__ . '/../database/blueprints.db'); } @@ -55,28 +55,32 @@ function db_blueprints(): SQLite3 * Take a SQLite3 database connection, a query string, and an array of parameters. Prepare the query and * bind the parameters with proper type casting. Then execute the query and return the result. */ -function db_query(SQLite3 $db, $query, array $params = []) +function db_query($db, $query, $params = []) { $stmt = $db->prepare($query); if (!empty($params)) foreach ($params as $key => $value) $stmt->bindValue($key, $value, getSQLiteType($value)); - db_log($query); - return $stmt->execute(); + $start = microtime(true); + $r = $stmt->execute(); + db_log($query, microtime(true) - $start); + return $r; } /** * Take a SQLite3 database connection and a query string. Execute the query and return the result. */ -function db_exec(SQLite3 $db, $query) +function db_exec($db, $query) { - db_log($query); - return $db->exec($query); + $start = microtime(true); + $r = $db->exec($query); + db_log($query, microtime(true) - $start); + return $r; } /** * Take a SQLite3 database connection, a column name, and a value. Execute a COUNT query to see if the value * exists in the column. Return true if the value exists, false otherwise. */ -function db_exists(SQLite3 $db, $table, $column, $value, $caseInsensitive = true) +function db_exists($db, $table, $column, $value, $caseInsensitive = true) { if ($caseInsensitive) { $query = "SELECT 1 FROM $table WHERE $column = :v COLLATE NOCASE LIMIT 1"; @@ -104,8 +108,9 @@ function getSQLiteType($value): int /** * Log the given query string to the db debug log. */ -function db_log($query) +function db_log($query, $timeTaken = 0) { $GLOBALS['queries']++; - if (env('debug', false)) $GLOBALS['query_log'][] = $query; + $GLOBALS['query_time'] += $timeTaken; + if (env('debug', false)) $GLOBALS['query_log'][] = [$query, $timeTaken]; } diff --git a/src/env.php b/src/env.php index d09dcdd..3fc1ab1 100644 --- a/src/env.php +++ b/src/env.php @@ -36,5 +36,12 @@ function env_load($filePath) */ function env($key, $default = null) { - return $_ENV[$key] ?? $_SERVER[$key] ?? (getenv($key) ?: $default); + $v = $_ENV[$key] ?? $_SERVER[$key] ?? (getenv($key) ?: $default); + return match(true) { + $v === 'true' => true, + $v === 'false' => false, + is_numeric($v) => (int) $v, + is_float($v) => (float) $v, + default => $v + }; } diff --git a/src/helpers.php b/src/helpers.php index 6b31a1d..06b3fa7 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -171,7 +171,7 @@ function percent($num, $denom, $precision = 4): int * the data is up to date with every request without having to query the database every use within, for example, a * template. Will return false if the field does not exist, or the entire wallet array if no field is specified. */ -function wallet($field = ''): array|int +function wallet($field = '') { if (empty($GLOBALS['wallet'])) { $GLOBALS['wallet'] = db_query( @@ -188,9 +188,38 @@ function wallet($field = ''): array|int /** * Format an array of strings to a ul element. */ -function array_to_ul(array $array) +function array_to_ul($array) { $html = ''; foreach ($array as $item) $html .= "
  • $item
  • "; return "
      $html
    "; } + +/** + * Start a keyed stopwatch to measure the time between two points in the code. + */ +function stopwatch_start($key) +{ + if (!env('debug', false)) return; + $GLOBALS['stopwatch'][$key] = microtime(true); +} + +/** + * Stop a keyed stopwatch. Stores the time in the global $stopwatch array under the key. + */ +function stopwatch_stop($key) +{ + if (!env('debug', false)) return; + if (empty($GLOBALS['stopwatch'][$key])) return 0; + $GLOBALS['stopwatch'][$key] = microtime(true) - $GLOBALS['stopwatch'][$key]; +} + +/** + * Get the stopwatch value and format it to within 10 digits. + */ +function stopwatch_get($key) +{ + if (!env('debug', false)) return; + if (empty($GLOBALS['stopwatch'][$key])) return 0; + return number_format($GLOBALS['stopwatch'][$key], 10); +} diff --git a/src/models/char.php b/src/models/char.php index c04a13e..34496bc 100644 --- a/src/models/char.php +++ b/src/models/char.php @@ -24,7 +24,7 @@ const currently = [ * of overrides to set additional fields. A character's name must be unique, but this function does not check for * that. Returns the created character's ID. */ -function char_create($user_id, $name, array $overrides = []): int +function char_create($user_id, $name, $overrides = []): int { // Prep the data and merge in any overrides $data = ['user_id' => $user_id, 'name' => $name]; @@ -65,7 +65,7 @@ function char_location_create($char_id, $x = 0, $y = 0, $currently = 0) * Create the character's gear table. A character's gear is where they store their equipped items. * @TODO: implement initial gear */ -function char_gear_create($char_id, array $initialGear = []) +function char_gear_create($char_id, $initialGear = []) { if (db_query(db_live(), "INSERT INTO char_gear (char_id) VALUES (:p)", [':p' => $char_id]) === false) { throw new Exception('Failed to create character gear. (cgc)'); @@ -94,7 +94,7 @@ function char_count($user_id): int /** * Get a an array of id => [name, level] for all characters associated with an account ID. */ -function char_list($user_id): array +function char_list($user_id) { $stmt = db_query(db_live(), "SELECT id, name, level FROM characters WHERE user_id = :u", [':u' => $user_id]); if ($stmt === false) throw new Exception('Failed to list characters. (cl)'); @@ -110,7 +110,7 @@ function char_list($user_id): array /** * Get a character's location info by their character ID. Returns the location's data as an associative array. */ -function char_get_location($char_id): array +function char_get_location($char_id) { // Get the location $location = db_query(db_live(), "SELECT * FROM char_locations WHERE char_id = :p", [':p' => $char_id])->fetchArray(SQLITE3_ASSOC); diff --git a/src/models/items.php b/src/models/items.php index a40ad99..d10cbd9 100644 --- a/src/models/items.php +++ b/src/models/items.php @@ -57,10 +57,3 @@ const item_qualities = [ 5 => 'Excellent', 6 => 'Masterwork', ]; - -/** - * Create an item - */ -function create_item($name, array $type, array $opts) { - -} diff --git a/src/render.php b/src/render.php index 3f8e364..aba2e98 100644 --- a/src/render.php +++ b/src/render.php @@ -31,7 +31,7 @@ function page_layout($layout = '') /** * Shorthand to render a page with the current layout. */ -function page($view, array $data = []) +function page($view, $data = []) { return render("layouts/" . page_layout(), ['view' => "pages/$view"] + $data); } diff --git a/src/router.php b/src/router.php index 5a002b5..db128e9 100644 --- a/src/router.php +++ b/src/router.php @@ -7,7 +7,7 @@ * Example: * `router_add($routes, 'GET', '/posts/:id', function($id) { echo "Viewing post $id"; });` */ -function router_add(array &$routes, $method, $route, callable $handler) +function router_add(&$routes, $method, $route, $handler) { // Expand the route into segments and make dynamic segments into a common placeholder $segments = array_map(function($segment) { @@ -33,7 +33,7 @@ function router_add(array &$routes, $method, $route, callable $handler) * * @return array ['code', 'handler', 'params'] */ -function router_lookup(array $routes, $method, $uri): array +function router_lookup($routes, $method, $uri) { // node is a reference to our current location in the node tree $node = $routes; diff --git a/templates/components/debug_query_log.php b/templates/components/debug_query_log.php index 003f99e..f8334bb 100644 --- a/templates/components/debug_query_log.php +++ b/templates/components/debug_query_log.php @@ -1,5 +1,11 @@

    Query Log

    queries were executed.

    - $query

    "; ?> + ({$time}s) {$query[0]}

    "; + } + ?>
    diff --git a/templates/components/debug_stopwatch.php b/templates/components/debug_stopwatch.php new file mode 100644 index 0000000..383d6a1 --- /dev/null +++ b/templates/components/debug_stopwatch.php @@ -0,0 +1,6 @@ +
    +

    Stopwatches

    +

    Page execution took seconds.

    +

    Bootstrap: seconds

    +

    Router: seconds

    +
    diff --git a/templates/layouts/basic.php b/templates/layouts/basic.php index 5598f18..fccc412 100644 --- a/templates/layouts/basic.php +++ b/templates/layouts/basic.php @@ -46,10 +46,16 @@

    © Dragon Knight

    q

    +

    qt

    +

    t

    v

    - +