Skip to content

Commit

Permalink
use gs algorithm for ko
Browse files Browse the repository at this point in the history
  • Loading branch information
inker committed Jan 15, 2024
1 parent 198a917 commit 1e7d27d
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 160 deletions.
70 changes: 0 additions & 70 deletions src/engine/backtracking/ko.ts

This file was deleted.

23 changes: 16 additions & 7 deletions src/engine/predicates/uefa/ko/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import type Team from 'model/team/KnockoutTeam'
import { type Predicate } from 'engine/backtracking/gs'
import getSmallestArrayLength from 'utils/getSmallestArrayLength'

import incompatibleCountries from '../utils/incompatibleCountries'

const isFrom = (country: string) => (team: Team) => team.country === country

const isFromCountryOf = (team: Team) => isFrom(team.country)

export default (season: number): Predicate<Team> => {
const isCountryIncompatibleWith = incompatibleCountries(season)

const areCompatible = (a: Team, b: Team) =>
a.country !== b.country &&
a.group !== b.group &&
!isCountryIncompatibleWith(a)(b)
return (picked, groups, groupIndex) => {
const { group: pickedGroup } = picked
const group = groups[groupIndex]
const currentPotIndex = getSmallestArrayLength(groups)

const canFit = (pair: readonly Team[], picked: Team) =>
pair.length === 0 || (pair.length === 1 && areCompatible(picked, pair[0]))
const isImpossible =
group.length > currentPotIndex ||
group.some(team => team.group === pickedGroup) ||
group.some(isFromCountryOf(picked)) ||
group.some(isCountryIncompatibleWith(picked))

return (picked, groups, groupIndex) => canFit(groups[groupIndex], picked)
return !isImpossible
}
}
53 changes: 0 additions & 53 deletions src/model/WorkerData.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { type FixedArray } from './types'

interface GsWorkerData<T> {
season: number
pots: readonly (readonly T[])[]
Expand Down Expand Up @@ -50,54 +48,3 @@ export const deserializeGsWorkerData = <T>(
selectedTeam: teams[selectedTeamIndex],
}
}

export interface KoWorkerData<T> {
season: number
pots: FixedArray<readonly T[], 2>
matchups: readonly (readonly [T, T])[]
}

export interface KoWorkerDataSerialized<T> {
season: number
teams: readonly T[]
pots: FixedArray<readonly number[], 2>
matchups: readonly (readonly [number, number])[]
}

export const serializeKoWorkerData = <T>(
data: KoWorkerData<T>,
): KoWorkerDataSerialized<T> => {
const teams = [...data.pots.flat(), ...data.matchups.flat()]

const indexByTeam = new Map(teams.map((item, i) => [item, i] as const))

const getIndexByTeam = (item: T) => indexByTeam.get(item)!

return {
...data,
teams,
pots: [data.pots[0].map(getIndexByTeam), data.pots[1].map(getIndexByTeam)],
matchups: data.matchups.map(
matchup =>
[getIndexByTeam(matchup[0]), getIndexByTeam(matchup[1])] as const,
),
}
}

export const deserializeKoWorkerData = <T>(
data: KoWorkerDataSerialized<T>,
): KoWorkerData<T> => {
const { teams, pots: potsSerialized, matchups: matchupsSerialized } = data

return {
...data,
pots: [
potsSerialized[0].map(i => teams[i]),
potsSerialized[1].map(i => teams[i]),
],
matchups: matchupsSerialized.map(matchup => [
teams[matchup[0]],
teams[matchup[1]],
]),
}
}
29 changes: 21 additions & 8 deletions src/pages/cl/ko/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { random, shuffle } from 'lodash'
import { orderBy, random, shuffle } from 'lodash'

import { type FixedArray } from 'model/types'
import type Team from 'model/team/KnockoutTeam'
import { serializeKoWorkerData } from 'model/WorkerData'
import { serializeGsWorkerData } from 'model/WorkerData'

import usePopup from 'store/usePopup'
import useDrawId from 'store/useDrawId'
Expand Down Expand Up @@ -80,22 +80,35 @@ function CLKO({ season, pots: initialPots }: Props) {
newPots: FixedArray<readonly Team[], 2>,
newMatchups: readonly [Team, Team][],
) => {
const [newGwPot, newRuPot] = newPots
const initialGwPot = initialPots[0]
// @ts-expect-error Expected
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
const selectedTeam = newMatchups.find(m => m.length === 1)?.at(-1)!
const groups = initialGwPot.map(gw => {
const ru = newMatchups.find(pair => pair[1] === gw)?.[0]
return ru ? [gw, ru] : [gw]
})
try {
return await getPossiblePairingsResponse(
serializeKoWorkerData({
const allPossibleGroups = await getPossiblePairingsResponse(
serializeGsWorkerData({
season,
pots: newPots,
matchups: newMatchups,
pots: [[], newRuPot],
groups,
selectedTeam,
}),
)
return orderBy(
allPossibleGroups.map(i => newGwPot.indexOf(groups[i][0])),
)
} catch (err) {
setPopup({
error: 'Could not determine possible pairings',
})
throw err
}
},
[season, getPossiblePairingsResponse],
[season, initialPots, getPossiblePairingsResponse],
)

const handleBallPick = useCallback(
Expand Down Expand Up @@ -155,7 +168,7 @@ function CLKO({ season, pots: initialPots }: Props) {
() =>
possiblePairings &&
pots[0].filter((team, i) => possiblePairings.includes(i)),
[possiblePairings],
[possiblePairings, pots],
)

const completed = currentMatchupNum >= initialPots[0].length
Expand Down
15 changes: 8 additions & 7 deletions src/pages/cl/ko/worker.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import memoizeOne from 'memoize-one'

import { getPossiblePairings } from 'engine/backtracking/ko'
import { allPossibleGroups } from 'engine/backtracking/gs'
import getPredicate from 'engine/predicates/uefa/ko'
import type Team from 'model/team/KnockoutTeam'
import {
type KoWorkerDataSerialized,
deserializeKoWorkerData,
type GsWorkerDataSerialized,
deserializeGsWorkerData,
} from 'model/WorkerData'
import exposeWorker, { type ExposedFuncType } from 'utils/worker/expose'

Expand All @@ -21,13 +21,14 @@ const eqFunc = (newArgs: GetPredicateParams, oldArgs: GetPredicateParams) =>

const getPredicateMemoized = memoizeOne(getPredicate, eqFunc)

const func = (data: KoWorkerDataSerialized<Team>) => {
const { season, pots, matchups } = deserializeKoWorkerData(data)
const func = (data: GsWorkerDataSerialized<Team>) => {
const { season, pots, groups, selectedTeam } = deserializeGsWorkerData(data)

const predicate = getPredicateMemoized(season)
return getPossiblePairings({
return allPossibleGroups({
pots,
matchups,
groups,
picked: selectedTeam,
predicate,
})
}
Expand Down
29 changes: 21 additions & 8 deletions src/pages/el/ko/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { random, shuffle } from 'lodash'
import { orderBy, random, shuffle } from 'lodash'

import { type FixedArray } from 'model/types'
import type Team from 'model/team/KnockoutTeam'
import { serializeKoWorkerData } from 'model/WorkerData'
import { serializeGsWorkerData } from 'model/WorkerData'

import usePopup from 'store/usePopup'
import useDrawId from 'store/useDrawId'
Expand Down Expand Up @@ -85,22 +85,35 @@ function ELKO({ season, pots: initialPots }: Props) {
newPots: FixedArray<readonly Team[], 2>,
newMatchups: readonly [Team, Team][],
) => {
const [newGwPot, newRuPot] = newPots
const initialGwPot = initialPots[0]
// @ts-expect-error Expected
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
const selectedTeam = newMatchups.find(m => m.length === 1)?.at(-1)!
const groups = initialGwPot.map(gw => {
const ru = newMatchups.find(pair => pair[1] === gw)?.[0]
return ru ? [gw, ru] : [gw]
})
try {
return await getPossiblePairingsResponse(
serializeKoWorkerData({
const allPossibleGroups = await getPossiblePairingsResponse(
serializeGsWorkerData({
season,
pots: newPots,
matchups: newMatchups,
pots: [[], newRuPot],
groups,
selectedTeam,
}),
)
return orderBy(
allPossibleGroups.map(i => newGwPot.indexOf(groups[i][0])),
)
} catch (err) {
setPopup({
error: 'Could not determine possible pairings',
})
throw err
}
},
[season, getPossiblePairingsResponse],
[season, initialPots, getPossiblePairingsResponse],
)

const handleBallPick = useCallback(
Expand Down Expand Up @@ -160,7 +173,7 @@ function ELKO({ season, pots: initialPots }: Props) {
() =>
possiblePairings &&
pots[0].filter((team, i) => possiblePairings.includes(i)),
[possiblePairings],
[possiblePairings, pots],
)

const completed = currentMatchupNum >= initialPots[0].length
Expand Down
15 changes: 8 additions & 7 deletions src/pages/el/ko/worker.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import memoizeOne from 'memoize-one'

import { getPossiblePairings } from 'engine/backtracking/ko'
import { allPossibleGroups } from 'engine/backtracking/gs'
import getPredicate from 'engine/predicates/uefa/ko'
import type Team from 'model/team/KnockoutTeam'
import {
type KoWorkerDataSerialized,
deserializeKoWorkerData,
type GsWorkerDataSerialized,
deserializeGsWorkerData,
} from 'model/WorkerData'
import exposeWorker, { type ExposedFuncType } from 'utils/worker/expose'

Expand All @@ -21,13 +21,14 @@ const eqFunc = (newArgs: GetPredicateParams, oldArgs: GetPredicateParams) =>

const getPredicateMemoized = memoizeOne(getPredicate, eqFunc)

const func = (data: KoWorkerDataSerialized<Team>) => {
const { season, pots, matchups } = deserializeKoWorkerData(data)
const func = (data: GsWorkerDataSerialized<Team>) => {
const { season, pots, groups, selectedTeam } = deserializeGsWorkerData(data)

const predicate = getPredicateMemoized(season)
return getPossiblePairings({
return allPossibleGroups({
pots,
matchups,
groups,
picked: selectedTeam,
predicate,
})
}
Expand Down

0 comments on commit 1e7d27d

Please sign in to comment.