Skip to content

Commit

Permalink
Fix sort order of equip to be same as the game
Browse files Browse the repository at this point in the history
  • Loading branch information
rassvet2 committed Feb 14, 2024
1 parent 8bebbd4 commit d6ad969
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 5 deletions.
79 changes: 79 additions & 0 deletions common/sortUtils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable valid-jsdoc */
import {isNumber} from 'common/checkVariableTypeUtil';

export enum SortingOrder{
Expand All @@ -22,4 +23,82 @@ export const sortTwoUnknownValues = (valueA: unknown, valueB: unknown,
}
};

type Comparator<Item> = (a: Item, b: Item) => number;

const Ordering = {
/** They are equals. */
Equal: 0,
/** The first value is sorted after the second. */
First: +1,
/** The second value is sorted after the first. */
Second: -1,
} as const;

const isNully = (x: unknown): x is null | undefined => {
return x === null || x === undefined;
};

/**
* @param keySelector
* A mapping function to extract key from an array element.
* Note that this function can return null or undefined,
* but these values are treated as greater than other values.
* @param comparatorFn
* This comparator functions are applied in order, starting with the first,
* and if the previous returns 0, the next is applied.
* When all functions s return 0, it means the two elements are equal.
* @return a comparator function.
*/
export const buildComparator = <Item, Key>(
keySelector: (item: Item) => (Key | null | undefined),
...comparatorFn: Comparator<Key>[]
): Comparator<Item> => {
return (firstItem, secondItem) => {
if (firstItem === secondItem) return Ordering.Equal;
const first = keySelector(firstItem);
const second = keySelector(secondItem);
if (first === second) return Ordering.Equal;

if (isNully(first) || isNully(second)) {
return (first === second) ? Ordering.Equal :
isNully(first) ? Ordering.First :
isNully(second) ? Ordering.Second :
'unreachable' as never;
}

for (const comparator of comparatorFn) {
const ordering = comparator(first, second);
if (ordering != Ordering.Equal) return ordering;
}

return Ordering.Equal;
};
};

const numberAscending: Comparator<number> = (a, b) => a - b;
const numberDescending: Comparator<number> = (a, b) => b - a;
const stringAscending: Comparator<string> = (a, b) => a.localeCompare(b);
const stringDescending: Comparator<string> = (a, b) => b.localeCompare(a);
const numericStringAscending = buildComparator(parseFloat, numberAscending);
const numericStringDescending = buildComparator(parseFloat, numberDescending);
export const Comparators = {
numberAscending, numberDescending,
stringAscending, stringDescending,
numericStringAscending, numericStringDescending,
} as const;

export const buildArrayIndexComparator = <Item>(
array: readonly Item[],
order: SortingOrder = SortingOrder.Ascending,
) => {
const comparator = order === SortingOrder.Ascending ?
Comparators.numberAscending :
Comparators.numberDescending;
return buildComparator<Item, number>(
(item) => {
const index = array.indexOf(item);
return index >= 0 ? index : null;
},
comparator,
);
};
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import styles from './AddToInventoryDialog.module.scss';
import {Button, Dialog, DialogActions, DialogContent, DialogTitle, useMediaQuery, useTheme} from '@mui/material';
import {
Button, Dialog, DialogActions, DialogContent, DialogTitle,
useMediaQuery, useTheme,
} from '@mui/material';
import React, {useEffect, useMemo, useReducer} from 'react';
import {useTranslation} from 'next-i18next';
import {useForm} from 'react-hook-form';
import {DropPieceIdWithProbAndCount, EquipmentsById} from 'components/calculationInput/PiecesCalculationCommonTypes';
import {
DropPieceIdWithProbAndCount, EquipmentsById,
} from 'components/calculationInput/PiecesCalculationCommonTypes';
import {InventoryForm} from './InventoryUpdateDialog';
import ObtainedPieceBox from './ObtainedPieceBox';
import {useStore} from 'stores/WizStore';
import {PieceState} from './PiecesInventory';
import {Comparators, SortingOrder, buildArrayIndexComparator, buildComparator} from 'common/sortUtils';
import { Equipment, EquipmentCategories } from 'model/Equipment';

const AddToInventoryDialog = ({
open,
Expand All @@ -34,11 +41,38 @@ const AddToInventoryDialog = ({
open && notifyOpened();
}, [open]);

const testNum = [1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1];
console.log(`${testNum}`);
console.log(`asc: ${testNum.toSorted(Comparators.numberAscending)}`);
console.log(`dsc: ${testNum.toSorted(Comparators.numberDescending)}`);
const testStr = ['ccc', , 'aaa', null, 'aab', 'acc', 'dca'];
console.log(`${testStr}`);
console.log(`asc: ${testStr.toSorted(buildComparator((x) => x, Comparators.stringAscending))}`);

const equipListComparator = useMemo(() => {
buildComparator((e) => e.tier, Comparators.numberDescending)
return buildComparator(
(piece: PieceState) => equipById.get(piece.pieceId),
);
}, [equipById]);

const pieceIds = useMemo(() => drops.map((drop) => drop.id), [drops]);
const pieces = useMemo(() => {
// 20-3: Necklace, Watch, Bag
// 20-4: Watch, Charm, Badge
// 13-1: Shoes, Gloves, Hat
// descending tier -> descending category order?
return Array.from(piecesState.values())
.filter((state) => pieceIds.includes(state.pieceId) && state.needCount > 0);
}, [piecesState, pieceIds]);
.filter((state) => pieceIds.includes(state.pieceId) && state.needCount > 0)
.toSorted(buildComparator(
(piece) => equipById.get(piece.pieceId),
buildComparator((e) => e.tier, Comparators.numberDescending),
buildComparator((e) => e.category, buildArrayIndexComparator(
EquipmentCategories,
SortingOrder.Descending
)),
));
}, [piecesState, pieceIds, equipById]);
const defaultValues = useMemo(() => {
return pieces.reduce<InventoryForm>((acc, piece) => {
acc[piece.pieceId] = '';
Expand Down
9 changes: 8 additions & 1 deletion model/Equipment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,16 @@ export enum GameServer {
China = 'China',
}

export const EquipmentCategories = [
'Hat', 'Gloves', 'Shoes',
'Bag', 'Badge', 'Hairpin',
'Charm', 'Watch', 'Necklace',
] as const;
export type EquipmentCategory = typeof EquipmentCategories[number];

export interface Equipment {
id: string
category: string
category: EquipmentCategory
tier: number
icon: string
jpName: string
Expand Down

0 comments on commit d6ad969

Please sign in to comment.