Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 21 additions & 22 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ in late game critical situations (like tied, 0 outs, bases loaded) there should
zgmb should have more doubles and triples https://discord.com/channels/290013534023057409/944392892905037885/1332600467502661717

bulk actions - tables should be aware that rows are players who have pids. add bulk/all/select operations at table-level through ... menu
- some way in typescript to impose the type of metadata in a table - rows can only have one type of metadata (or no metadata in some rows is fine, like drafted players table)
- some way in typescript to impose the type of metadata in a table - rows can only have one type of metadata (or no metadata in some rows is fine, like drafted players table)
- if this was done, then most metadata type checks like `metadata.type === "player"` in BulkActions and ExportPlayers would not be needed, those are just for typescript
- something like this works, but is kind of annoying with the generic being needed in various places:
`type RowOfType<T extends RowMetadata["type"]> = T extends RowMetadata["type"] ? { metadata: Extract<RowMetadata, { type: T }>; other: string } : never;`
Expand Down Expand Up @@ -1561,8 +1561,8 @@ football penalty later
- option to apply penalty on kickoff, for extra points
- option to redo punt or not
- double foul after change of possession edge cases to test
- If this spot is normally a touchback, the ball is placed on the 20-yard line.
- If normally a safety, place the ball on one-yard line.
- If this spot is normally a touchback, the ball is placed on the 20-yard line.
- If normally a safety, place the ball on one-yard line.

football game sim later
- should separate catch and run after catch
Expand Down Expand Up @@ -1824,7 +1824,6 @@ force resign button under lock ratings, keep a man on one team
- @dooby moogey#2784

award editor
- Finals MVP displays regular season stats if you change it to someone who also played in that same finals. https://discord.com/channels/290013534023057409/290015591216054273/787237109924495412
- support editing seasons older than the start of the league

UI for selecting a custom set of teams in a new league
Expand Down Expand Up @@ -2521,7 +2520,7 @@ make AI smarter about contracts

cache index updating
- currenty: check if the indexed property has changed, and only update a specific index then
- would be better: make _dirtyIndexes per index, not per store
- would be better: make _dirtyIndexes per index, not per store
- even better: incrementally update index

later
Expand Down Expand Up @@ -2949,21 +2948,21 @@ update formulas

@TheRealGWood#4891 Team traits
Have you ever played CK2?
I ask because the more comments I see like that reddit post the more simple I think replacing Mood with traits would work.
I ask because the more comments I see like that reddit post the more simple I think replacing Mood with traits would work.
CK2 uses them. You can created TRID trait ID store as 1-10 or something fir starters-
Injury prone - 10% higher injury frequency
Chronic injury- 20% higher injury chance, 10% higher - result from injury
Injury prone - 10% higher injury frequency
Chronic injury- 20% higher injury chance, 10% higher - result from injury
Erratic- -5 Mood, -5 for every other erratic or Ego
Ego- +5 mood, -10 minutes under 30 or usuage under 28%
Demands a Trade- Won’t resign. -10 team mood
Demands a Trade- Won’t resign. -10 team mood
Team leader- +5 team mood, +1DIQ team, +1 OIQ team
Savy Vet- better team progs, +1 team mood , unhappy if losing
Savy Vet- better team progs, +1 team mood , unhappy if losing
Team player- +1 team mood
Ball hog- -1 team mood +1 mood if usuage over 25%
Farewell season- +3 in all traits final game and forced retire at end of season, +1 team mood
Franchise player - (only over 70’s) max 1 per team or mood= -10,
Star- team mood + 0.5, savy vets more likley to sign
Bookworm- +3 OIQ/DIQ
Franchise player - (only over 70’s) max 1 per team or mood= -10,
Star- team mood + 0.5, savy vets more likley to sign
Bookworm- +3 OIQ/DIQ
Idiot- -3 OIQ/ DIQ , team mood -1

Team traits-
Expand All @@ -2978,21 +2977,21 @@ update formulas
Hardworking
Workaholic

Out of Shape
Prime Shape
Out of Shape
Prime Shape

Streaky
Consistent
Streaky
Consistent

Clutch
Choke artist
Choke artist

And settable traits-
Minutes restriction
Load management
Minutes restriction
Load management
Sixth man (won’t start)
Primary ball handler
Primary scorer
Primary ball handler
Primary scorer
Go to Shooter

FUTURE
Expand Down
14 changes: 14 additions & 0 deletions src/worker/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ import type { IDBPIndex, IDBPObjectStore } from "@dumbmatter/idb";
import { upgradeGamesVersion65, type LeagueDB } from "../db/connectLeague.ts";
import playMenu from "./playMenu.ts";
import toolsMenu from "./toolsMenu.ts";
import { getFinalsStatsForPlayer } from "../core/season/finalsMvp.basketball.ts";
import addFirstNameShort from "../util/addFirstNameShort.ts";
import statsBaseball from "../core/team/stats.baseball.ts";
import { extraRatings } from "../views/playerRatings.ts";
Expand Down Expand Up @@ -4527,6 +4528,19 @@ const updateAwards = async (
awards: any,
conditions: Conditions,
): Promise<any> => {
if (isSport("basketball") && awards.finalsMvp?.pid !== undefined) {
const finalsStats = await getFinalsStatsForPlayer(
awards.season,
awards.finalsMvp.pid,
);
if (finalsStats) {
awards.finalsMvp = {
...awards.finalsMvp,
...finalsStats,
};
}
}

const awardsInitial = await idb.getCopy.awards(
{
season: awards.season,
Expand Down
109 changes: 6 additions & 103 deletions src/worker/core/season/doAwards.basketball.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,16 @@ import {
} from "./awards.ts";
import { idb } from "../../db/index.ts";
import { defaultGameAttributes, g, helpers } from "../../util/index.ts";
import type {
Conditions,
Game,
PlayerFiltered,
} from "../../../common/types.ts";
import type { Conditions, PlayerFiltered } from "../../../common/types.ts";
import type {
AwardPlayer,
AwardPlayerDefense,
Awards,
} from "../../../common/types.basketball.ts";
import { orderBy } from "../../../common/utils.ts";
import {
getPlayoffSeriesMVP,
getRealFinalsMvp,
} from "./finalsMvp.basketball.ts";

const getPlayerInfoOffense = (p: PlayerFiltered): AwardPlayer => {
return {
Expand Down Expand Up @@ -90,102 +89,6 @@ const makeTeams = <T>(
];
};

const getPlayoffSeriesMVP = (players: PlayerFiltered[], games: Game[]) => {
if (games.length === 0) {
return;
}

// Champ is winner of the last game in the series
const wonSeriesTid = games.at(-1)!.won.tid;

// Calculate sum of game scores for each player
const playerInfos: Map<
number,
{
pid: number;
score: number;
tid: number;
pts: number;
trb: number;
ast: number;
gp: number;
}
> = new Map();

for (const game of games) {
for (const t of game.teams) {
for (const p of t.players) {
const info = playerInfos.get(p.pid) ?? {
pid: p.pid,
score: 0,
tid: t.tid,
pts: 0,
trb: 0,
ast: 0,
gp: 0,
};

// 75% bonus for the winning team
const factor = t.tid === wonSeriesTid ? 1.75 : 1;
info.score += factor * helpers.gameScore(p);
info.pts += p.pts;
info.trb += p.drb + p.orb;
info.ast += p.ast;
if (p.min > 0) {
info.gp += 1;
}
playerInfos.set(p.pid, info);
}
}
}

const playerArray = orderBy(
Array.from(playerInfos.values()),
"score",
"desc",
);

if (!playerArray[0]) {
return;
}

const { pid } = playerArray[0];
const p = players.find((p2) => p2.pid === pid);

if (p) {
return {
pid: p.pid,
name: p.name,
tid: p.tid,
pts: playerArray[0].pts / playerArray[0].gp,
trb: playerArray[0].trb / playerArray[0].gp,
ast: playerArray[0].ast / playerArray[0].gp,
};
}
};

const getRealFinalsMvp = async (
players: PlayerFiltered[],
): Promise<AwardPlayer | undefined> => {
const games = await idb.cache.games.getAll();

// Last game of the season will have the two finals teams
const finalsTids = games.at(-1)?.teams.map((t) => t.tid);
if (finalsTids === undefined) {
return;
}

// Get all playoff games between those two teams - that will be all finals games
const finalsGames = games.filter(
(game) =>
game.playoffs &&
finalsTids.includes(game.teams[0].tid) &&
finalsTids.includes(game.teams[1].tid),
);

return getPlayoffSeriesMVP(players, finalsGames);
};

const getSemiFinalsMvp = async (
players: PlayerFiltered[],
): Promise<AwardPlayer[]> => {
Expand Down Expand Up @@ -484,7 +387,7 @@ const doAwards = async (conditions: Conditions) => {

if (champTeam) {
const champTid = champTeam.tid;
finalsMvp = await getRealFinalsMvp(players);
finalsMvp = await getRealFinalsMvp(players, g.get("season"));

// If for some reason there is no Finals MVP (like if the finals box scores were not found), use total playoff stats
if (finalsMvp === undefined) {
Expand Down
Loading