diff --git a/pb_migrations/1757710506_created_player_stats.js b/pb_migrations/1757710506_created_player_stats.js new file mode 100644 index 0000000..828f08d --- /dev/null +++ b/pb_migrations/1757710506_created_player_stats.js @@ -0,0 +1,235 @@ +/// +migrate((app) => { + const collection = new Collection({ + "createRule": null, + "deleteRule": null, + "fields": [ + { + "autogeneratePattern": "", + "hidden": false, + "id": "text3208210256", + "max": 0, + "min": 0, + "name": "id", + "pattern": "^[a-z0-9]+$", + "presentable": false, + "primaryKey": true, + "required": true, + "system": true, + "type": "text" + }, + { + "cascadeDelete": false, + "collectionId": "pbc_3072146508", + "hidden": false, + "id": "relation2582050271", + "maxSelect": 1, + "minSelect": 0, + "name": "player_id", + "presentable": false, + "required": false, + "system": false, + "type": "relation" + }, + { + "hidden": false, + "id": "json4231605813", + "maxSize": 1, + "name": "player_name", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_976G", + "max": 0, + "min": 0, + "name": "first_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + }, + { + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_njLe", + "max": 0, + "min": 0, + "name": "last_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": false, + "system": false, + "type": "text" + }, + { + "cascadeDelete": false, + "collectionId": "pbc_1568971955", + "hidden": false, + "id": "relation694999214", + "maxSelect": 1, + "minSelect": 0, + "name": "team_id", + "presentable": false, + "required": false, + "system": false, + "type": "relation" + }, + { + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_ZNMy", + "max": 0, + "min": 0, + "name": "team_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + }, + { + "cascadeDelete": false, + "collectionId": "pbc_340646327", + "hidden": false, + "id": "relation869376999", + "maxSelect": 1, + "minSelect": 0, + "name": "tournament_id", + "presentable": false, + "required": false, + "system": false, + "type": "relation" + }, + { + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_nxTv", + "max": 0, + "min": 0, + "name": "tournament_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + }, + { + "hidden": false, + "id": "number103159226", + "max": null, + "min": null, + "name": "matches", + "onlyInt": false, + "presentable": false, + "required": false, + "system": false, + "type": "number" + }, + { + "hidden": false, + "id": "json2732118329", + "maxSize": 1, + "name": "wins", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json724428801", + "maxSize": 1, + "name": "losses", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json3041953980", + "maxSize": 1, + "name": "margin_of_victory", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json1531431708", + "maxSize": 1, + "name": "margin_of_loss", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json1062535948", + "maxSize": 1, + "name": "total_cups_won_by", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json4249694556", + "maxSize": 1, + "name": "total_cups_lost_by", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json3154249934", + "maxSize": 1, + "name": "total_cups_made", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json3227208027", + "maxSize": 1, + "name": "total_cups_against", + "presentable": false, + "required": false, + "system": false, + "type": "json" + } + ], + "id": "pbc_135889471", + "indexes": [], + "listRule": null, + "name": "player_stats", + "system": false, + "type": "view", + "updateRule": null, + "viewQuery": "\n SELECT\n (p.id || '_' || t.id || '_' || tour.id) as id,\n p.id as player_id,\n (p.first_name || ' ' || p.last_name) as player_name,\n p.first_name,\n p.last_name,\n t.id as team_id,\n t.name as team_name,\n tour.id as tournament_id,\n tour.name as tournament_name,\n COUNT(m.id) as matches,\n SUM(CASE\n WHEN (m.home = t.id AND m.home_cups > m.away_cups) OR\n (m.away = t.id AND m.away_cups > m.home_cups)\n THEN 1 ELSE 0\n END) as wins,\n SUM(CASE\n WHEN (m.home = t.id AND m.home_cups < m.away_cups) OR\n (m.away = t.id AND m.away_cups < m.home_cups)\n THEN 1 ELSE 0\n END) as losses,\n AVG(CASE\n WHEN m.home = t.id AND m.home_cups > m.away_cups\n THEN m.home_cups - m.away_cups\n WHEN m.away = t.id AND m.away_cups > m.home_cups\n THEN m.away_cups - m.home_cups\n ELSE NULL\n END) as margin_of_victory,\n AVG(CASE\n WHEN m.home = t.id AND m.home_cups < m.away_cups\n THEN m.away_cups - m.home_cups\n WHEN m.away = t.id AND m.away_cups < m.home_cups\n THEN m.home_cups - m.away_cups\n ELSE NULL\n END) as margin_of_loss,\n SUM(CASE\n WHEN m.home = t.id THEN m.home_cups\n WHEN m.away = t.id THEN m.away_cups\n ELSE 0\n END) as total_cups_won_by,\n SUM(CASE\n WHEN m.home = t.id THEN m.away_cups\n WHEN m.away = t.id THEN m.home_cups\n ELSE 0\n END) as total_cups_lost_by,\n SUM(CASE\n WHEN m.home = t.id THEN m.home_cups\n WHEN m.away = t.id THEN m.away_cups\n ELSE 0\n END) as total_cups_made,\n SUM(CASE\n WHEN m.home = t.id THEN m.away_cups\n WHEN m.away = t.id THEN m.home_cups\n ELSE 0\n END) as total_cups_against\n FROM players p\n JOIN teams t ON json_extract(t.players, '$[*]') LIKE '%' || p.id || '%'\n JOIN matches m ON (m.home = t.id OR m.away = t.id)\n JOIN tournaments tour ON m.tournament = tour.id\n WHERE m.status = 'ended'\n GROUP BY p.id, t.id, tour.id", + "viewRule": null + }); + + return app.save(collection); +}, (app) => { + const collection = app.findCollectionByNameOrId("pbc_135889471"); + + return app.delete(collection); +}) diff --git a/pb_migrations/1757710693_updated_player_stats.js b/pb_migrations/1757710693_updated_player_stats.js new file mode 100644 index 0000000..35a4dae --- /dev/null +++ b/pb_migrations/1757710693_updated_player_stats.js @@ -0,0 +1,194 @@ +/// +migrate((app) => { + const collection = app.findCollectionByNameOrId("pbc_135889471") + + // update collection data + unmarshal({ + "viewQuery": "SELECT\n (p.id || '_' || t.id || '_' || tour.id) as id,\n p.id as player_id,\n (p.first_name || ' ' || p.last_name) as player_name,\n t.id as team_id,\n t.name as team_name,\n tour.id as tournament_id,\n tour.name as tournament_name,\n COUNT(m.id) as matches,\n SUM(CASE\n WHEN (m.home = t.id AND m.home_cups > m.away_cups) OR\n (m.away = t.id AND m.away_cups > m.home_cups)\n THEN 1 ELSE 0\n END) as wins,\n SUM(CASE\n WHEN (m.home = t.id AND m.home_cups < m.away_cups) OR\n (m.away = t.id AND m.away_cups < m.home_cups)\n THEN 1 ELSE 0\n END) as losses,\n SUM(CASE\n WHEN m.home = t.id THEN m.home_cups\n WHEN m.away = t.id THEN m.away_cups\n ELSE 0\n END) as total_cups_made,\n SUM(CASE\n WHEN m.home = t.id THEN m.away_cups\n WHEN m.away = t.id THEN m.home_cups\n ELSE 0\n END) as total_cups_against\n FROM players p, teams t, matches m, tournaments tour\n WHERE\n t.players LIKE '%\"' || p.id || '\"%' AND\n (m.home = t.id OR m.away = t.id) AND\n m.tournament = tour.id AND\n m.status = 'ended'\n GROUP BY p.id, t.id, tour.id" + }, collection) + + // remove field + collection.fields.removeById("_clone_976G") + + // remove field + collection.fields.removeById("_clone_njLe") + + // remove field + collection.fields.removeById("_clone_ZNMy") + + // remove field + collection.fields.removeById("_clone_nxTv") + + // remove field + collection.fields.removeById("json3041953980") + + // remove field + collection.fields.removeById("json1531431708") + + // remove field + collection.fields.removeById("json1062535948") + + // remove field + collection.fields.removeById("json4249694556") + + // add field + collection.fields.addAt(4, new Field({ + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_YqC8", + "max": 0, + "min": 0, + "name": "team_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + })) + + // add field + collection.fields.addAt(6, new Field({ + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_jZTo", + "max": 0, + "min": 0, + "name": "tournament_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + })) + + return app.save(collection) +}, (app) => { + const collection = app.findCollectionByNameOrId("pbc_135889471") + + // update collection data + unmarshal({ + "viewQuery": "\n SELECT\n (p.id || '_' || t.id || '_' || tour.id) as id,\n p.id as player_id,\n (p.first_name || ' ' || p.last_name) as player_name,\n p.first_name,\n p.last_name,\n t.id as team_id,\n t.name as team_name,\n tour.id as tournament_id,\n tour.name as tournament_name,\n COUNT(m.id) as matches,\n SUM(CASE\n WHEN (m.home = t.id AND m.home_cups > m.away_cups) OR\n (m.away = t.id AND m.away_cups > m.home_cups)\n THEN 1 ELSE 0\n END) as wins,\n SUM(CASE\n WHEN (m.home = t.id AND m.home_cups < m.away_cups) OR\n (m.away = t.id AND m.away_cups < m.home_cups)\n THEN 1 ELSE 0\n END) as losses,\n AVG(CASE\n WHEN m.home = t.id AND m.home_cups > m.away_cups\n THEN m.home_cups - m.away_cups\n WHEN m.away = t.id AND m.away_cups > m.home_cups\n THEN m.away_cups - m.home_cups\n ELSE NULL\n END) as margin_of_victory,\n AVG(CASE\n WHEN m.home = t.id AND m.home_cups < m.away_cups\n THEN m.away_cups - m.home_cups\n WHEN m.away = t.id AND m.away_cups < m.home_cups\n THEN m.home_cups - m.away_cups\n ELSE NULL\n END) as margin_of_loss,\n SUM(CASE\n WHEN m.home = t.id THEN m.home_cups\n WHEN m.away = t.id THEN m.away_cups\n ELSE 0\n END) as total_cups_won_by,\n SUM(CASE\n WHEN m.home = t.id THEN m.away_cups\n WHEN m.away = t.id THEN m.home_cups\n ELSE 0\n END) as total_cups_lost_by,\n SUM(CASE\n WHEN m.home = t.id THEN m.home_cups\n WHEN m.away = t.id THEN m.away_cups\n ELSE 0\n END) as total_cups_made,\n SUM(CASE\n WHEN m.home = t.id THEN m.away_cups\n WHEN m.away = t.id THEN m.home_cups\n ELSE 0\n END) as total_cups_against\n FROM players p\n JOIN teams t ON json_extract(t.players, '$[*]') LIKE '%' || p.id || '%'\n JOIN matches m ON (m.home = t.id OR m.away = t.id)\n JOIN tournaments tour ON m.tournament = tour.id\n WHERE m.status = 'ended'\n GROUP BY p.id, t.id, tour.id" + }, collection) + + // add field + collection.fields.addAt(3, new Field({ + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_976G", + "max": 0, + "min": 0, + "name": "first_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + })) + + // add field + collection.fields.addAt(4, new Field({ + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_njLe", + "max": 0, + "min": 0, + "name": "last_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": false, + "system": false, + "type": "text" + })) + + // add field + collection.fields.addAt(6, new Field({ + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_ZNMy", + "max": 0, + "min": 0, + "name": "team_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + })) + + // add field + collection.fields.addAt(8, new Field({ + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_nxTv", + "max": 0, + "min": 0, + "name": "tournament_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + })) + + // add field + collection.fields.addAt(12, new Field({ + "hidden": false, + "id": "json3041953980", + "maxSize": 1, + "name": "margin_of_victory", + "presentable": false, + "required": false, + "system": false, + "type": "json" + })) + + // add field + collection.fields.addAt(13, new Field({ + "hidden": false, + "id": "json1531431708", + "maxSize": 1, + "name": "margin_of_loss", + "presentable": false, + "required": false, + "system": false, + "type": "json" + })) + + // add field + collection.fields.addAt(14, new Field({ + "hidden": false, + "id": "json1062535948", + "maxSize": 1, + "name": "total_cups_won_by", + "presentable": false, + "required": false, + "system": false, + "type": "json" + })) + + // add field + collection.fields.addAt(15, new Field({ + "hidden": false, + "id": "json4249694556", + "maxSize": 1, + "name": "total_cups_lost_by", + "presentable": false, + "required": false, + "system": false, + "type": "json" + })) + + // remove field + collection.fields.removeById("_clone_YqC8") + + // remove field + collection.fields.removeById("_clone_jZTo") + + return app.save(collection) +}) diff --git a/pb_migrations/1757710817_updated_player_stats.js b/pb_migrations/1757710817_updated_player_stats.js new file mode 100644 index 0000000..18817fe --- /dev/null +++ b/pb_migrations/1757710817_updated_player_stats.js @@ -0,0 +1,96 @@ +/// +migrate((app) => { + const collection = app.findCollectionByNameOrId("pbc_135889471") + + // update collection data + unmarshal({ + "name": "player_stats_per_tournament" + }, collection) + + // remove field + collection.fields.removeById("_clone_YqC8") + + // remove field + collection.fields.removeById("_clone_jZTo") + + // add field + collection.fields.addAt(4, new Field({ + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_XGbN", + "max": 0, + "min": 0, + "name": "team_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + })) + + // add field + collection.fields.addAt(6, new Field({ + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_uud6", + "max": 0, + "min": 0, + "name": "tournament_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + })) + + return app.save(collection) +}, (app) => { + const collection = app.findCollectionByNameOrId("pbc_135889471") + + // update collection data + unmarshal({ + "name": "player_stats" + }, collection) + + // add field + collection.fields.addAt(4, new Field({ + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_YqC8", + "max": 0, + "min": 0, + "name": "team_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + })) + + // add field + collection.fields.addAt(6, new Field({ + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_jZTo", + "max": 0, + "min": 0, + "name": "tournament_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + })) + + // remove field + collection.fields.removeById("_clone_XGbN") + + // remove field + collection.fields.removeById("_clone_uud6") + + return app.save(collection) +}) diff --git a/pb_migrations/1757710882_created_player_stats.js b/pb_migrations/1757710882_created_player_stats.js new file mode 100644 index 0000000..5c6c723 --- /dev/null +++ b/pb_migrations/1757710882_created_player_stats.js @@ -0,0 +1,180 @@ +/// +migrate((app) => { + const collection = new Collection({ + "createRule": null, + "deleteRule": null, + "fields": [ + { + "autogeneratePattern": "", + "hidden": false, + "id": "text3208210256", + "max": 0, + "min": 0, + "name": "id", + "pattern": "^[a-z0-9]+$", + "presentable": false, + "primaryKey": true, + "required": true, + "system": true, + "type": "text" + }, + { + "cascadeDelete": false, + "collectionId": "pbc_3072146508", + "hidden": false, + "id": "relation2582050271", + "maxSelect": 1, + "minSelect": 0, + "name": "player_id", + "presentable": false, + "required": false, + "system": false, + "type": "relation" + }, + { + "hidden": false, + "id": "json4231605813", + "maxSize": 1, + "name": "player_name", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "cascadeDelete": false, + "collectionId": "pbc_1568971955", + "hidden": false, + "id": "relation694999214", + "maxSelect": 1, + "minSelect": 0, + "name": "team_id", + "presentable": false, + "required": false, + "system": false, + "type": "relation" + }, + { + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_fQu1", + "max": 0, + "min": 0, + "name": "team_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + }, + { + "hidden": false, + "id": "number103159226", + "max": null, + "min": null, + "name": "matches", + "onlyInt": false, + "presentable": false, + "required": false, + "system": false, + "type": "number" + }, + { + "hidden": false, + "id": "json2732118329", + "maxSize": 1, + "name": "wins", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json724428801", + "maxSize": 1, + "name": "losses", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json3154249934", + "maxSize": 1, + "name": "total_cups_made", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json3227208027", + "maxSize": 1, + "name": "total_cups_against", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json2379943496", + "maxSize": 1, + "name": "win_percentage", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json3165107022", + "maxSize": 1, + "name": "avg_cups_per_match", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json3041953980", + "maxSize": 1, + "name": "margin_of_victory", + "presentable": false, + "required": false, + "system": false, + "type": "json" + }, + { + "hidden": false, + "id": "json1531431708", + "maxSize": 1, + "name": "margin_of_loss", + "presentable": false, + "required": false, + "system": false, + "type": "json" + } + ], + "id": "pbc_1358894712", + "indexes": [], + "listRule": null, + "name": "player_stats", + "system": false, + "type": "view", + "updateRule": null, + "viewQuery": "SELECT\n (p.id || '_' || t.id) as id,\n p.id as player_id,\n (p.first_name || ' ' || p.last_name) as player_name,\n t.id as team_id,\n t.name as team_name,\n COUNT(m.id) as matches,\n SUM(CASE\n WHEN (m.home = t.id AND m.home_cups > m.away_cups) OR\n (m.away = t.id AND m.away_cups > m.home_cups)\n THEN 1 ELSE 0\n END) as wins,\n SUM(CASE\n WHEN (m.home = t.id AND m.home_cups < m.away_cups) OR\n (m.away = t.id AND m.away_cups < m.home_cups)\n THEN 1 ELSE 0\n END) as losses,\n SUM(CASE\n WHEN m.home = t.id THEN m.home_cups\n WHEN m.away = t.id THEN m.away_cups\n ELSE 0\n END) as total_cups_made,\n SUM(CASE\n WHEN m.home = t.id THEN m.away_cups\n WHEN m.away = t.id THEN m.home_cups\n ELSE 0\n END) as total_cups_against,\n -- Additional calculated stats\n ROUND((CAST(SUM(CASE\n WHEN (m.home = t.id AND m.home_cups > m.away_cups) OR\n (m.away = t.id AND m.away_cups > m.home_cups)\n THEN 1 ELSE 0\n END) AS REAL) / COUNT(m.id)) * 100, 2) as win_percentage,\n ROUND(CAST(SUM(CASE\n WHEN m.home = t.id THEN m.home_cups\n WHEN m.away = t.id THEN m.away_cups\n ELSE 0\n END) AS REAL) / COUNT(m.id), 2) as avg_cups_per_match,\n -- Margin calculations\n AVG(CASE\n WHEN m.home = t.id AND m.home_cups > m.away_cups\n THEN m.home_cups - m.away_cups\n WHEN m.away = t.id AND m.away_cups > m.home_cups\n THEN m.away_cups - m.home_cups\n ELSE NULL\n END) as margin_of_victory,\n AVG(CASE\n WHEN m.home = t.id AND m.home_cups < m.away_cups\n THEN m.away_cups - m.home_cups\n WHEN m.away = t.id AND m.away_cups < m.home_cups\n THEN m.home_cups - m.away_cups\n ELSE NULL\n END) as margin_of_loss\n FROM players p, teams t, matches m, tournaments tour\n WHERE\n t.players LIKE '%\"' || p.id || '\"%' AND\n (m.home = t.id OR m.away = t.id) AND\n m.tournament = tour.id AND\n m.status = 'ended'\n GROUP BY p.id, t.id", + "viewRule": null + }); + + return app.save(collection); +}, (app) => { + const collection = app.findCollectionByNameOrId("pbc_1358894712"); + + return app.delete(collection); +}) diff --git a/pb_migrations/1757711182_updated_player_stats.js b/pb_migrations/1757711182_updated_player_stats.js new file mode 100644 index 0000000..ec9878a --- /dev/null +++ b/pb_migrations/1757711182_updated_player_stats.js @@ -0,0 +1,57 @@ +/// +migrate((app) => { + const collection = app.findCollectionByNameOrId("pbc_1358894712") + + // update collection data + unmarshal({ + "viewQuery": "SELECT\n p.id as id,\n p.id as player_id,\n (p.first_name || ' ' || p.last_name) as player_name,\n COUNT(m.id) as matches,\n SUM(CASE\n WHEN (m.home = t.id AND m.home_cups > m.away_cups) OR\n (m.away = t.id AND m.away_cups > m.home_cups)\n THEN 1 ELSE 0\n END) as wins,\n SUM(CASE\n WHEN (m.home = t.id AND m.home_cups < m.away_cups) OR\n (m.away = t.id AND m.away_cups < m.home_cups)\n THEN 1 ELSE 0\n END) as losses,\n SUM(CASE\n WHEN m.home = t.id THEN m.home_cups\n WHEN m.away = t.id THEN m.away_cups\n ELSE 0\n END) as total_cups_made,\n SUM(CASE\n WHEN m.home = t.id THEN m.away_cups\n WHEN m.away = t.id THEN m.home_cups\n ELSE 0\n END) as total_cups_against,\n -- Win percentage\n ROUND((CAST(SUM(CASE\n WHEN (m.home = t.id AND m.home_cups > m.away_cups) OR\n (m.away = t.id AND m.away_cups > m.home_cups)\n THEN 1 ELSE 0\n END) AS REAL) / COUNT(m.id)) * 100, 2) as win_percentage,\n -- Average cups per match\n ROUND(CAST(SUM(CASE\n WHEN m.home = t.id THEN m.home_cups\n WHEN m.away = t.id THEN m.away_cups\n ELSE 0\n END) AS REAL) / COUNT(m.id), 2) as avg_cups_per_match,\n -- Margin of Victory\n ROUND(AVG(CASE\n WHEN m.home = t.id AND m.home_cups > m.away_cups\n THEN m.home_cups - m.away_cups\n WHEN m.away = t.id AND m.away_cups > m.home_cups\n THEN m.away_cups - m.home_cups\n ELSE NULL\n END), 2) as margin_of_victory,\n -- Margin of Loss\n ROUND(AVG(CASE\n WHEN m.home = t.id AND m.home_cups < m.away_cups\n THEN m.away_cups - m.home_cups\n WHEN m.away = t.id AND m.away_cups < m.home_cups\n THEN m.home_cups - m.away_cups\n ELSE NULL\n END), 2) as margin_of_loss\n FROM players p, teams t, matches m, tournaments tour\n WHERE\n t.players LIKE '%\"' || p.id || '\"%' AND\n (m.home = t.id OR m.away = t.id) AND\n m.tournament = tour.id AND\n m.status = 'ended'\n GROUP BY p.id" + }, collection) + + // remove field + collection.fields.removeById("relation694999214") + + // remove field + collection.fields.removeById("_clone_fQu1") + + return app.save(collection) +}, (app) => { + const collection = app.findCollectionByNameOrId("pbc_1358894712") + + // update collection data + unmarshal({ + "viewQuery": "SELECT\n (p.id || '_' || t.id) as id,\n p.id as player_id,\n (p.first_name || ' ' || p.last_name) as player_name,\n t.id as team_id,\n t.name as team_name,\n COUNT(m.id) as matches,\n SUM(CASE\n WHEN (m.home = t.id AND m.home_cups > m.away_cups) OR\n (m.away = t.id AND m.away_cups > m.home_cups)\n THEN 1 ELSE 0\n END) as wins,\n SUM(CASE\n WHEN (m.home = t.id AND m.home_cups < m.away_cups) OR\n (m.away = t.id AND m.away_cups < m.home_cups)\n THEN 1 ELSE 0\n END) as losses,\n SUM(CASE\n WHEN m.home = t.id THEN m.home_cups\n WHEN m.away = t.id THEN m.away_cups\n ELSE 0\n END) as total_cups_made,\n SUM(CASE\n WHEN m.home = t.id THEN m.away_cups\n WHEN m.away = t.id THEN m.home_cups\n ELSE 0\n END) as total_cups_against,\n -- Additional calculated stats\n ROUND((CAST(SUM(CASE\n WHEN (m.home = t.id AND m.home_cups > m.away_cups) OR\n (m.away = t.id AND m.away_cups > m.home_cups)\n THEN 1 ELSE 0\n END) AS REAL) / COUNT(m.id)) * 100, 2) as win_percentage,\n ROUND(CAST(SUM(CASE\n WHEN m.home = t.id THEN m.home_cups\n WHEN m.away = t.id THEN m.away_cups\n ELSE 0\n END) AS REAL) / COUNT(m.id), 2) as avg_cups_per_match,\n -- Margin calculations\n AVG(CASE\n WHEN m.home = t.id AND m.home_cups > m.away_cups\n THEN m.home_cups - m.away_cups\n WHEN m.away = t.id AND m.away_cups > m.home_cups\n THEN m.away_cups - m.home_cups\n ELSE NULL\n END) as margin_of_victory,\n AVG(CASE\n WHEN m.home = t.id AND m.home_cups < m.away_cups\n THEN m.away_cups - m.home_cups\n WHEN m.away = t.id AND m.away_cups < m.home_cups\n THEN m.home_cups - m.away_cups\n ELSE NULL\n END) as margin_of_loss\n FROM players p, teams t, matches m, tournaments tour\n WHERE\n t.players LIKE '%\"' || p.id || '\"%' AND\n (m.home = t.id OR m.away = t.id) AND\n m.tournament = tour.id AND\n m.status = 'ended'\n GROUP BY p.id, t.id" + }, collection) + + // add field + collection.fields.addAt(3, new Field({ + "cascadeDelete": false, + "collectionId": "pbc_1568971955", + "hidden": false, + "id": "relation694999214", + "maxSelect": 1, + "minSelect": 0, + "name": "team_id", + "presentable": false, + "required": false, + "system": false, + "type": "relation" + })) + + // add field + collection.fields.addAt(4, new Field({ + "autogeneratePattern": "", + "hidden": false, + "id": "_clone_fQu1", + "max": 0, + "min": 0, + "name": "team_name", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": true, + "system": false, + "type": "text" + })) + + return app.save(collection) +}) diff --git a/src/features/bracket/components/match-card.tsx b/src/features/bracket/components/match-card.tsx index 5addac5..123bcad 100644 --- a/src/features/bracket/components/match-card.tsx +++ b/src/features/bracket/components/match-card.tsx @@ -30,7 +30,12 @@ export const MatchCard: React.FC = ({ from_loser: match.home_from_loser, team: match.home, seed: match.home_seed, - cups: match.status === "ended" ? match.home_cups : undefined + cups: match.status === "ended" ? match.home_cups : undefined, + isWinner: + match.status === "ended" && + match.home_cups !== undefined && + match.away_cups !== undefined && + match.home_cups > match.away_cups, }), [match] ); @@ -40,7 +45,12 @@ export const MatchCard: React.FC = ({ from_loser: match.away_from_loser, team: match.away, seed: match.away_seed, - cups: match.status === "ended" ? match.away_cups : undefined + cups: match.status === "ended" ? match.away_cups : undefined, + isWinner: + match.status === "ended" && + match.away_cups !== undefined && + match.home_cups !== undefined && + match.away_cups > match.home_cups, }), [match] ); @@ -81,37 +91,45 @@ export const MatchCard: React.FC = ({ }, [match]); const handleFormSubmit = useCallback( - async (data: { home_cups: number; away_cups: number; ot_count: number }) => { - await end.mutate({ data: { - ...data, - matchId: match.id - }}); + async (data: { + home_cups: number; + away_cups: number; + ot_count: number; + }) => { + await end.mutate({ + data: { + ...data, + matchId: match.id, + }, + }); editSheet.close(); }, [match.id, editSheet] ); const handleSpeakerClick = useCallback(() => { - if ('speechSynthesis' in window && match.home?.name && match.away?.name) { + if ("speechSynthesis" in window && match.home?.name && match.away?.name) { const utterance = new SpeechSynthesisUtterance( `${match.home.name} vs. ${match.away.name}` ); - + const voices = window.speechSynthesis.getVoices(); - - const preferredVoice = voices.find(voice => - voice.lang.startsWith('en') && - voice.name.includes('Daniel') - ) || voices.find(voice => voice.lang.startsWith('en') && voice.default); - + + const preferredVoice = + voices.find( + (voice) => + voice.lang.startsWith("en") && voice.name.includes("Daniel") + ) || + voices.find((voice) => voice.lang.startsWith("en") && voice.default); + if (preferredVoice) { utterance.voice = preferredVoice; } - + utterance.rate = 0.9; utterance.volume = 0.8; utterance.pitch = 1.0; - + window.speechSynthesis.speak(utterance); } }, [match.home?.name, match.away?.name]); @@ -157,17 +175,19 @@ export const MatchCard: React.FC = ({ )} - - - + {showControls && ( + + + + )} diff --git a/src/features/bracket/components/match-slot.tsx b/src/features/bracket/components/match-slot.tsx index 20a340a..4783804 100644 --- a/src/features/bracket/components/match-slot.tsx +++ b/src/features/bracket/components/match-slot.tsx @@ -1,5 +1,6 @@ import { Flex, Text } from "@mantine/core"; import React from "react"; +import { CrownIcon } from "@phosphor-icons/react"; import { SeedBadge } from "./seed-badge"; import { TeamInfo } from "@/features/teams/types"; @@ -9,6 +10,7 @@ interface MatchSlotProps { team?: TeamInfo; seed?: number; cups?: number; + isWinner?: boolean; } export const MatchSlot: React.FC = ({ @@ -16,25 +18,49 @@ export const MatchSlot: React.FC = ({ from_loser, team, seed, - cups + cups, + isWinner }) => ( {(seed && seed > 0) ? : undefined} - - {team ? ( - {team.name} - ) : from ? ( - - {from_loser ? "Loser" : "Winner"} of Match {from} - - ) : ( - - TBD - - )} + + + {team ? ( + <> + 12 ? (team.name.length > 18 ? '10px' : '11px') : 'xs'} + truncate + style={{ minWidth: 0, flex: 1 }} + > + {team.name} + + {isWinner && ( + + )} + + ) : from ? ( + + {from_loser ? "Loser" : "Winner"} of Match {from} + + ) : ( + + TBD + + )} + { cups !== undefined ? ( - {cups} + {cups} ) : undefined } diff --git a/src/features/matches/server.ts b/src/features/matches/server.ts index 29eff21..aa7ed9e 100644 --- a/src/features/matches/server.ts +++ b/src/features/matches/server.ts @@ -58,8 +58,8 @@ export const generateTournamentBracket = createServerFn() home_cups: 0, away_cups: 0, ot_count: 0, - home_from_lid: match.home_from_lid, - away_from_lid: match.away_from_lid, + home_from_lid: match.home_from_lid === null ? -1 : match.home_from_lid, + away_from_lid: match.away_from_lid === null ? -1 : match.away_from_lid, home_from_loser: match.home_from_loser || false, away_from_loser: match.away_from_loser || false, is_losers_bracket: false, @@ -102,8 +102,8 @@ export const generateTournamentBracket = createServerFn() home_cups: 0, away_cups: 0, ot_count: 0, - home_from_lid: match.home_from_lid, - away_from_lid: match.away_from_lid, + home_from_lid: match.home_from_lid === null ? -1 : match.home_from_lid, + away_from_lid: match.away_from_lid === null ? -1 : match.away_from_lid, home_from_loser: match.home_from_loser || false, away_from_loser: match.away_from_loser || false, is_losers_bracket: true, @@ -190,6 +190,8 @@ export const endMatch = createServerFn() // winner -> where to send match winner to, loser same const { winner, loser } = await pbAdmin.getChildMatches(matchId); + console.log(winner, loser) + // reset match check if (winner && winner.reset) { const awayTeamWon = match.away === matchWinner;