From 1216e76381e35cc6549de2405435a823c277d41f Mon Sep 17 00:00:00 2001 From: David Westgate Date: Sun, 9 Mar 2025 12:54:39 -0700 Subject: [PATCH 1/9] add back comments --- app.json | 3 ++- components/BuyInSelector.tsx | 2 +- components/ChipDistributionSummary.tsx | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app.json b/app.json index 46d6b54..476dcb4 100644 --- a/app.json +++ b/app.json @@ -9,7 +9,8 @@ "userInterfaceStyle": "automatic", "newArchEnabled": true, "ios": { - "supportsTablet": true + "supportsTablet": true, + "bundleIdentifier": "com.anonymous.pokerchipshelper" }, "android": { "adaptiveIcon": { diff --git a/components/BuyInSelector.tsx b/components/BuyInSelector.tsx index d9356a1..e6fe07b 100644 --- a/components/BuyInSelector.tsx +++ b/components/BuyInSelector.tsx @@ -61,7 +61,7 @@ const BuyInSelector: React.FC = ({ /> - {`${i18n.t("selected_buy_in")}: `} + {`${i18n.t("selected_buy_in")} `} {buyInAmount !== null ? `${selectedCurrency} ${buyInAmount}` : i18n.t("none")} diff --git a/components/ChipDistributionSummary.tsx b/components/ChipDistributionSummary.tsx index 01a88d4..df0008c 100644 --- a/components/ChipDistributionSummary.tsx +++ b/components/ChipDistributionSummary.tsx @@ -12,6 +12,8 @@ interface ChipDistributionSummaryProps { selectedCurrency: string; } +const reverseFib: number[] = [8, 5, 3, 2, 1]; + const ChipDistributionSummary = ({ playerCount, buyInAmount, @@ -47,6 +49,8 @@ const ChipDistributionSummary = ({ return current; }; + // Bound for the value of the highest chip + // This is somewhat arbitray, but 1/3 to 1/4 is reasonable depending on the number of colors. const maxDenomination = useMemo(() => { if (totalChipsCount.length > 3) { return findFloorDenomination(buyInAmount / 3); @@ -60,6 +64,7 @@ const ChipDistributionSummary = ({ [buyInAmount, playerCount] ); + // The total value of all chips distributed to a single player. Ideally should be equal to buyInAmount const totalValue = useMemo(() => { let value = 0; for (let i = 0; i < totalChipsCount.length; i++) { @@ -68,11 +73,14 @@ const ChipDistributionSummary = ({ return value; }, [distributions, denominations]); + // Maximum quantity of each chip color which may be distributed to a single player before running out const maxPossibleDistribution = useMemo( () => totalChipsCount.map((v) => Math.floor(v / playerCount)), [totalChipsCount, playerCount] ); + // Redenominate the chips in case of failure to properly distribute. + // Move the shuffle index to the next lowest denomination, and keep all else same const redenominate = useCallback( ( invalidDenomination: validDenomination[], @@ -102,6 +110,7 @@ const ChipDistributionSummary = ({ [] ); + // Dynamically set denominations and distributions from changing inputs useEffect(() => { let testDenomination: validDenomination[] = []; const numColors = totalChipsCount.length; @@ -110,6 +119,7 @@ const ChipDistributionSummary = ({ testDistribution.push(0); } + // Start with max denominations, then push on the next adjacent lower denomination testDenomination.push(maxDenomination); let currentDenominationIndex: number = validDenominations.indexOf(maxDenomination); @@ -120,6 +130,9 @@ const ChipDistributionSummary = ({ } testDenomination.reverse(); + // Distribute the chips using the test denomination + // If distribution fails to equal the buy-in, redenominate and re-try + // Algorithm could be improved with more complexity and optimization let remainingValue = buyInAmount; let fail = true; let failCount = 0; @@ -162,6 +175,7 @@ const ChipDistributionSummary = ({ Date: Sun, 9 Mar 2025 14:30:45 -0700 Subject: [PATCH 2/9] better distribution with fibbonachi --- components/ChipDistributionSummary.tsx | 97 ++++++++++++++------------ 1 file changed, 53 insertions(+), 44 deletions(-) diff --git a/components/ChipDistributionSummary.tsx b/components/ChipDistributionSummary.tsx index df0008c..63d88f9 100644 --- a/components/ChipDistributionSummary.tsx +++ b/components/ChipDistributionSummary.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useEffect, useMemo, useState } from "react"; -import { View, Text, StyleSheet } from "react-native"; +import { View, Text } from "react-native"; import { ColorValue } from "react-native"; import i18n from "@/i18n/i18n"; import styles from "@/styles/styles"; @@ -22,7 +22,7 @@ const ChipDistributionSummary = ({ selectedCurrency = "$", }: ChipDistributionSummaryProps) => { const validDenominations: validDenomination[] = [ - 0.05, 0.1, 0.25, 0.5, 1, 2, 2.5, 5, 10, 20, 50, 100, + 0.05, 0.1, 0.25, 1, 5, 10, 20, 50, 100, ]; const [denominations, setDenominations] = useState([]); const [distributions, setDistributions] = useState([]); @@ -38,26 +38,38 @@ const ChipDistributionSummary = ({ | 5 | 10 | 20 + | 25 | 50 | 100; const findFloorDenomination = (target: number): validDenomination => { let current: validDenomination = validDenominations[0]; - validDenominations.forEach((value, index) => { + validDenominations.forEach((value, _) => { if (value < target) current = value; }); return current; }; // Bound for the value of the highest chip - // This is somewhat arbitray, but 1/3 to 1/4 is reasonable depending on the number of colors. - const maxDenomination = useMemo(() => { - if (totalChipsCount.length > 3) { - return findFloorDenomination(buyInAmount / 3); - } else { - return findFloorDenomination(buyInAmount / 4); + // This is somewhat arbitray and imperfect, but 1/3 to 1/5 is reasonable depending on the number of colors. + const maxDenomination: validDenomination = useMemo(() => { + let max: validDenomination; + switch (totalChipsCount.length) { + case 5: + case 4: + max = findFloorDenomination(buyInAmount / 3); + break; + case 3: + max = findFloorDenomination(buyInAmount / 4); + break; + case 2: + case 1: + default: + max = findFloorDenomination(buyInAmount / 5); + break; } - }, [totalChipsCount]); + return max; + }, [totalChipsCount, buyInAmount]); const potValue = useMemo( () => buyInAmount * playerCount, @@ -67,7 +79,7 @@ const ChipDistributionSummary = ({ // The total value of all chips distributed to a single player. Ideally should be equal to buyInAmount const totalValue = useMemo(() => { let value = 0; - for (let i = 0; i < totalChipsCount.length; i++) { + for (let i = 0; i < distributions.length; i++) { value += distributions[i] * denominations[i]; } return value; @@ -81,7 +93,7 @@ const ChipDistributionSummary = ({ // Redenominate the chips in case of failure to properly distribute. // Move the shuffle index to the next lowest denomination, and keep all else same - const redenominate = useCallback( + const _redenominate = useCallback( ( invalidDenomination: validDenomination[], shuffleIndex: number @@ -113,56 +125,53 @@ const ChipDistributionSummary = ({ // Dynamically set denominations and distributions from changing inputs useEffect(() => { let testDenomination: validDenomination[] = []; - const numColors = totalChipsCount.length; - const testDistribution: number[] = []; - for (let i = 0; i < numColors; ++i) { - testDistribution.push(0); - } + const totalNumColors = totalChipsCount.length; // Start with max denominations, then push on the next adjacent lower denomination testDenomination.push(maxDenomination); let currentDenominationIndex: number = validDenominations.indexOf(maxDenomination); - for (let i = numColors - 2; i >= 0; i = i - 1) { + for ( + let i = totalNumColors - 2; + i >= 0 && currentDenominationIndex > 0; + i = i - 1 + ) { currentDenominationIndex -= 1; const currentDemoniation = validDenominations[currentDenominationIndex]; testDenomination.push(currentDemoniation); } testDenomination.reverse(); + let numColors = testDenomination.length; + + const testDistribution: number[] = []; + for (let i = 0; i < numColors; ++i) { + testDistribution.push(0); + } // Distribute the chips using the test denomination // If distribution fails to equal the buy-in, redenominate and re-try // Algorithm could be improved with more complexity and optimization let remainingValue = buyInAmount; - let fail = true; - let failCount = 0; - while (fail && failCount < 1) { - let stop = false; - while (remainingValue > 0 && !stop) { - let distributed = false; - for (let i = numColors - 1; i >= 0; i = i - 1) { - if (testDistribution[i] < maxPossibleDistribution[i]) { - if (remainingValue >= testDenomination[i]) { - testDistribution[i] = testDistribution[i] + 1; - remainingValue = remainingValue - testDenomination[i]; - distributed = true; - } + let stop = false; + while (remainingValue > 0 && !stop) { + let distributed = false; + for (let i = numColors - 1; i >= 0; i = i - 1) { + if (testDistribution[i] < maxPossibleDistribution[i]) { + for ( + let j = reverseFib[i]; + j > 0 && remainingValue >= testDenomination[i]; + j = j - 1 + ) { + testDistribution[i] = testDistribution[i] + 1; + remainingValue = remainingValue - testDenomination[i]; + distributed = true; } } - if (distributed == false) { - stop = true; - } } - if (remainingValue !== 0) { - const redenominateIndex = failCount % numColors; - testDenomination = redenominate(testDenomination, redenominateIndex); - failCount += 1; - fail = true; - } else { - fail = false; + if (distributed == false) { + stop = true; } } - setDenominations(testDenomination); setDistributions(testDistribution); }, [totalChipsCount, maxDenomination, buyInAmount, playerCount]); @@ -170,7 +179,7 @@ const ChipDistributionSummary = ({ return ( <> - {totalChipsCount.map((_, index) => ( + {denominations.map((denomination, index) => ( - {`${distributions[index]} ${i18n.t("chips")}: ${selectedCurrency}${denominations[index]} ${i18n.t("each")}`} + {`${distributions[index]} ${i18n.t("chips")}: ${selectedCurrency}${denomination} ${i18n.t("each")}`} ))} From bfa66d58564e88c385b19a6fd99a1cf54c2ddee6 Mon Sep 17 00:00:00 2001 From: David Westgate Date: Sun, 9 Mar 2025 14:59:08 -0700 Subject: [PATCH 3/9] limit ranges for buy in selector --- components/BuyInSelector.tsx | 13 +++++++++++-- components/ChipDistributionSummary.tsx | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/components/BuyInSelector.tsx b/components/BuyInSelector.tsx index e6fe07b..a280820 100644 --- a/components/BuyInSelector.tsx +++ b/components/BuyInSelector.tsx @@ -10,6 +10,14 @@ interface BuyInSelectorProps { } const defaultBuyInOptions = [10, 25, 50]; +const MIN = 1; +const MAX = 200; + +const parseRoundClamp = (num: string): number => { + const parsed = parseFloat(num); + const rounded = Math.round(parsed); + return Math.min(Math.max(rounded, MIN), MAX); +}; const BuyInSelector: React.FC = ({ setBuyInAmount, @@ -19,9 +27,9 @@ const BuyInSelector: React.FC = ({ const [buyInAmount, setBuyInAmountState] = useState(null); const handleCustomAmountChange = (value: string) => { - const numericValue = parseFloat(value); + const numericValue = parseRoundClamp(value); if (!isNaN(numericValue) && numericValue >= 0) { - setCustomAmount(value); + setCustomAmount(numericValue.toString()); setBuyInAmountState(numericValue); setBuyInAmount(numericValue); } else { @@ -55,6 +63,7 @@ const BuyInSelector: React.FC = ({ - {i18n.t("total_value")}: {selectedCurrency} {totalValue} + {i18n.t("total_value")}: {selectedCurrency} {totalValue.toFixed(2)} {selectedCurrency} {potValue} {i18n.t("pot")} From ca042b3afbc85bc68d59f8fdc0e212a1b321fc77 Mon Sep 17 00:00:00 2001 From: David Westgate Date: Sun, 9 Mar 2025 15:05:48 -0700 Subject: [PATCH 4/9] update buyin label --- components/BuyInSelector.tsx | 4 +--- i18n/en.json | 3 +-- i18n/es.json | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/components/BuyInSelector.tsx b/components/BuyInSelector.tsx index a280820..93eae83 100644 --- a/components/BuyInSelector.tsx +++ b/components/BuyInSelector.tsx @@ -58,14 +58,12 @@ const BuyInSelector: React.FC = ({ ))} - {i18n.t("custom_buy_in")} - diff --git a/i18n/en.json b/i18n/en.json index f671d03..da31ef9 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -8,8 +8,7 @@ "inr": "INR (₹)", "select_number_of_players": "Select the Number of Players:", "select_buyin_amount": "Select Buy-in Amount:", - "custom_buy_in": "Or enter a custom amount:", - "enter_custom_buy_in": "Enter custom buy-in", + "custom_buy_in": "Or, enter a custom amount:", "selected_buy_in": "Selected Buy-in:", "none": "None", "pick_an_image": "Pick an image", diff --git a/i18n/es.json b/i18n/es.json index cff8756..c39c4aa 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -8,8 +8,7 @@ "inr": "INR (₹)", "select_number_of_players": "Seleccionar número de jugadores:", "select_buyin_amount": "Seleccionar cantidad de buy-in:", - "custom_buy_in": "O ingresa una cantidad personalizada:", - "enter_custom_buy_in": "Ingresar buy-in personalizado", + "custom_buy_in": "O, ingresa una cantidad personalizada:", "selected_buy_in": "Buy-in seleccionado:", "none": "Ninguno", "pick_an_image": "Elige una imagen", From 01303b625aa61d32de6457f97943afb5726d64e9 Mon Sep 17 00:00:00 2001 From: David Westgate Date: Sun, 9 Mar 2025 15:10:14 -0700 Subject: [PATCH 5/9] stop rendering 0 dist chips --- components/ChipDistributionSummary.tsx | 32 +++++++++++++++----------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/components/ChipDistributionSummary.tsx b/components/ChipDistributionSummary.tsx index 686885b..3d8e7cb 100644 --- a/components/ChipDistributionSummary.tsx +++ b/components/ChipDistributionSummary.tsx @@ -179,20 +179,24 @@ const ChipDistributionSummary = ({ return ( <> - {denominations.map((denomination, index) => ( - - - {`${distributions[index]} ${i18n.t("chips")}: ${selectedCurrency}${denomination} ${i18n.t("each")}`} - - - ))} + {distributions.map((distribution, index) => { + return ( + distribution > 0 && ( + + + {`${distribution} ${i18n.t("chips")}: ${selectedCurrency}${denominations[index]} ${i18n.t("each")}`} + + + ) + ); + })} From abdffcef7116fd114abb23f66e36f169e67b945c Mon Sep 17 00:00:00 2001 From: David Westgate Date: Sun, 9 Mar 2025 15:45:20 -0700 Subject: [PATCH 6/9] fix rounding issue --- components/ChipDistributionSummary.tsx | 62 +++++++------------------- 1 file changed, 17 insertions(+), 45 deletions(-) diff --git a/components/ChipDistributionSummary.tsx b/components/ChipDistributionSummary.tsx index 3d8e7cb..4b8ce1a 100644 --- a/components/ChipDistributionSummary.tsx +++ b/components/ChipDistributionSummary.tsx @@ -50,8 +50,11 @@ const ChipDistributionSummary = ({ return current; }; + const round = useCallback((num: number) => Math.round(num * 100) / 100, []); + // Bound for the value of the highest chip // This is somewhat arbitray and imperfect, but 1/3 to 1/5 is reasonable depending on the number of colors. + // Could be possibly improved based on value of buy in amount const maxDenomination: validDenomination = useMemo(() => { let max: validDenomination; switch (totalChipsCount.length) { @@ -91,37 +94,6 @@ const ChipDistributionSummary = ({ [totalChipsCount, playerCount] ); - // Redenominate the chips in case of failure to properly distribute. - // Move the shuffle index to the next lowest denomination, and keep all else same - const _redenominate = useCallback( - ( - invalidDenomination: validDenomination[], - shuffleIndex: number - ): validDenomination[] => { - let moved = false; - const newDenomination: validDenomination[] = []; - for (let i = invalidDenomination.length - 1; i >= 0; i--) { - if (i > shuffleIndex) { - newDenomination.push(invalidDenomination[i]); - } else if (i == shuffleIndex) { - newDenomination.push(invalidDenomination[i]); - } else if (i < shuffleIndex && !moved) { - const nextLowestDenominationIndex = Math.max( - validDenominations.indexOf(invalidDenomination[i]) - 1, - 0 - ); - newDenomination.push(validDenominations[nextLowestDenominationIndex]); - moved = true; - } else { - newDenomination.push(invalidDenomination[i]); - } - } - newDenomination.reverse(); - return newDenomination; - }, - [] - ); - // Dynamically set denominations and distributions from changing inputs useEffect(() => { let testDenomination: validDenomination[] = []; @@ -148,24 +120,24 @@ const ChipDistributionSummary = ({ testDistribution.push(0); } - // Distribute the chips using the test denomination - // If distribution fails to equal the buy-in, redenominate and re-try - // Algorithm could be improved with more complexity and optimization + // Distribute the chips using the test denomination with a reverse fibbonaci preference + // Not optimal, nor correct under all inputs but works for most inputs + // Algorithm could be improved with more complexity and optimization (re-tries, redenominating, etc.) let remainingValue = buyInAmount; let stop = false; while (remainingValue > 0 && !stop) { let distributed = false; for (let i = numColors - 1; i >= 0; i = i - 1) { - if (testDistribution[i] < maxPossibleDistribution[i]) { - for ( - let j = reverseFib[i]; - j > 0 && remainingValue >= testDenomination[i]; - j = j - 1 - ) { - testDistribution[i] = testDistribution[i] + 1; - remainingValue = remainingValue - testDenomination[i]; - distributed = true; - } + for ( + let j = reverseFib[i]; + j > 0 && + remainingValue >= testDenomination[i] && + testDistribution[i] < maxPossibleDistribution[i]; + j = j - 1 + ) { + testDistribution[i] = testDistribution[i] + 1; + remainingValue = round(remainingValue - testDenomination[i]); + distributed = true; } } if (distributed == false) { @@ -200,7 +172,7 @@ const ChipDistributionSummary = ({ - {i18n.t("total_value")}: {selectedCurrency} {totalValue.toFixed(2)} + {i18n.t("total_value")}: {selectedCurrency} {round(totalValue)} {selectedCurrency} {potValue} {i18n.t("pot")} From 648d81564744814826bb459bda524630afc313f7 Mon Sep 17 00:00:00 2001 From: David Westgate Date: Sun, 9 Mar 2025 15:53:13 -0700 Subject: [PATCH 7/9] fix tests --- components/__tests__/BuyInSelector.test.tsx | 54 ++++++++++++++----- .../ChipDistributionSummary.test.tsx | 4 +- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/components/__tests__/BuyInSelector.test.tsx b/components/__tests__/BuyInSelector.test.tsx index ce29dbf..f9a8872 100644 --- a/components/__tests__/BuyInSelector.test.tsx +++ b/components/__tests__/BuyInSelector.test.tsx @@ -39,7 +39,9 @@ describe("BuyInSelector Component", () => { expect(getByText("$ 10")).toBeTruthy(); expect(getByText("$ 25")).toBeTruthy(); expect(getByText("$ 50")).toBeTruthy(); - expect(getByPlaceholderText("Enter custom buy-in")).toBeTruthy(); + expect( + getByPlaceholderText("Or, enter a custom amount: 1 - 200") + ).toBeTruthy(); expect(queryByText(/Selected Buy-in:.*None/i)).toBeTruthy(); }); @@ -53,24 +55,36 @@ describe("BuyInSelector Component", () => { it("sets a custom buy-in amount correctly", () => { const { getByPlaceholderText } = renderComponent(); - fireEvent.changeText(getByPlaceholderText("Enter custom buy-in"), "100"); + fireEvent.changeText( + getByPlaceholderText("Or, enter a custom amount: 1 - 200"), + "100" + ); expect(setBuyInAmount).toHaveBeenCalledWith(100); }); - it("resets custom amount if invalid input is entered", () => { + it("bound and validate custom amount if invalid input is entered", () => { const { getByPlaceholderText } = renderComponent(); - fireEvent.changeText(getByPlaceholderText("Enter custom buy-in"), "-10"); - expect(setBuyInAmount).toHaveBeenCalledWith(25); // Default reset + fireEvent.changeText( + getByPlaceholderText("Or, enter a custom amount: 1 - 200"), + "-10" + ); + expect(setBuyInAmount).toHaveBeenCalledWith(1); // Min value - fireEvent.changeText(getByPlaceholderText("Enter custom buy-in"), "abc"); - expect(setBuyInAmount).toHaveBeenCalledWith(25); + fireEvent.changeText( + getByPlaceholderText("Or, enter a custom amount: 1 - 200"), + "abc" + ); + expect(setBuyInAmount).toHaveBeenCalledWith(1); }); it("clears the custom amount when selecting a predefined option", () => { const { getByPlaceholderText, getByText } = renderComponent(); - fireEvent.changeText(getByPlaceholderText("Enter custom buy-in"), "100"); + fireEvent.changeText( + getByPlaceholderText("Or, enter a custom amount: 1 - 200"), + "100" + ); fireEvent.press(getByText("$ 50")); expect(setBuyInAmount).toHaveBeenCalledWith(50); }); @@ -78,13 +92,22 @@ describe("BuyInSelector Component", () => { it("handles valid and invalid input for custom amount correctly", () => { const { getByPlaceholderText } = renderComponent(); - fireEvent.changeText(getByPlaceholderText("Enter custom buy-in"), "75"); + fireEvent.changeText( + getByPlaceholderText("Or, enter a custom amount: 1 - 200"), + "75" + ); expect(setBuyInAmount).toHaveBeenCalledWith(75); - fireEvent.changeText(getByPlaceholderText("Enter custom buy-in"), "-5"); - expect(setBuyInAmount).toHaveBeenCalledWith(25); + fireEvent.changeText( + getByPlaceholderText("Or, enter a custom amount: 1 - 200"), + "-5" + ); + expect(setBuyInAmount).toHaveBeenCalledWith(1); - fireEvent.changeText(getByPlaceholderText("Enter custom buy-in"), "abc"); + fireEvent.changeText( + getByPlaceholderText("Or, enter a custom amount: 1 - 200"), + "abc" + ); expect(setBuyInAmount).toHaveBeenCalledWith(25); }); @@ -98,7 +121,7 @@ describe("BuyInSelector Component", () => { it("resets to default buy-in when custom input is cleared", () => { const { getByPlaceholderText } = renderComponent(); - const input = getByPlaceholderText("Enter custom buy-in"); + const input = getByPlaceholderText("Or, enter a custom amount: 1 - 200"); fireEvent.changeText(input, "75"); expect(setBuyInAmount).toHaveBeenCalledWith(75); @@ -110,7 +133,10 @@ describe("BuyInSelector Component", () => { it("updates state correctly when selecting predefined buy-in after entering a custom amount", () => { const { getByPlaceholderText, getByText } = renderComponent(); - fireEvent.changeText(getByPlaceholderText("Enter custom buy-in"), "200"); + fireEvent.changeText( + getByPlaceholderText("Or, enter a custom amount: 1 - 200"), + "200" + ); expect(setBuyInAmount).toHaveBeenCalledWith(200); fireEvent.press(getByText("$ 10")); diff --git a/components/__tests__/ChipDistributionSummary.test.tsx b/components/__tests__/ChipDistributionSummary.test.tsx index ef66610..936d7f8 100644 --- a/components/__tests__/ChipDistributionSummary.test.tsx +++ b/components/__tests__/ChipDistributionSummary.test.tsx @@ -7,8 +7,8 @@ describe("ChipDistributionSummary Component", () => { const playerCount = 4; const totalChipsCount = [100, 80, 60, 40, 20]; const buyInAmount = 20; - const expectedDistribution = [2, 2, 1, 2, 2]; - const expectedDenominations = [0.5, 1, 2, 2.5, 5]; + const expectedDistribution = [16, 12, 8, 6, 2]; + const expectedDenominations = [0.05, 0.1, 0.25, 1, 5]; const { getByText } = render( Date: Sun, 9 Mar 2025 16:04:20 -0700 Subject: [PATCH 8/9] change default chip selections --- components/ChipsSelector.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/ChipsSelector.tsx b/components/ChipsSelector.tsx index 4344e93..b77d54b 100644 --- a/components/ChipsSelector.tsx +++ b/components/ChipsSelector.tsx @@ -14,6 +14,7 @@ import styles from "@/styles/styles"; import i18n from "@/i18n/i18n"; const colors: ColorValue[] = ["white", "red", "green", "blue", "black"]; +const defaults = [100, 50, 50, 50, 50]; const ChipInputModal = ({ showModal, @@ -152,7 +153,7 @@ const ChipsSelector = ({ } else if (numberOfChips > totalChipsCount.length) { for (let colorIndex = 0; colorIndex < numberOfChips; ++colorIndex) { if (colorIndex >= newTotalChipsCount.length) { - const defaultTotal = 100 - colorIndex * 20; + const defaultTotal = defaults[colorIndex]; newTotalChipsCount.push(defaultTotal); } } From de723a5d8ab4d97fec00445f56b0d076893b4f49 Mon Sep 17 00:00:00 2001 From: David Westgate Date: Sun, 9 Mar 2025 16:35:02 -0700 Subject: [PATCH 9/9] add warning mechanism --- components/ChipDistributionSummary.tsx | 25 +++++++++++++++---- .../ChipDistributionSummary.test.tsx | 7 ++++++ i18n/en.json | 4 ++- i18n/es.json | 4 ++- styles/styles.ts | 2 +- 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/components/ChipDistributionSummary.tsx b/components/ChipDistributionSummary.tsx index 4b8ce1a..c2a4a38 100644 --- a/components/ChipDistributionSummary.tsx +++ b/components/ChipDistributionSummary.tsx @@ -1,8 +1,9 @@ import React, { useCallback, useEffect, useMemo, useState } from "react"; -import { View, Text } from "react-native"; +import { View, Text, Alert } from "react-native"; import { ColorValue } from "react-native"; import i18n from "@/i18n/i18n"; -import styles from "@/styles/styles"; +import styles, { COLORS } from "@/styles/styles"; +import { MaterialIcons } from "@expo/vector-icons"; interface ChipDistributionSummaryProps { playerCount: number; @@ -27,6 +28,10 @@ const ChipDistributionSummary = ({ const [denominations, setDenominations] = useState([]); const [distributions, setDistributions] = useState([]); + const showAlert = () => { + Alert.alert(i18n.t("warning"), i18n.t("chip_value_warn")); + }; + type validDenomination = | 0.05 | 0.1 @@ -171,9 +176,19 @@ const ChipDistributionSummary = ({ })} - - {i18n.t("total_value")}: {selectedCurrency} {round(totalValue)} - + + + {i18n.t("total_value")}: {selectedCurrency} {round(totalValue)}{" "} + + {round(totalValue) !== buyInAmount && ( + + )} + {selectedCurrency} {potValue} {i18n.t("pot")} diff --git a/components/__tests__/ChipDistributionSummary.test.tsx b/components/__tests__/ChipDistributionSummary.test.tsx index 936d7f8..f0ce2cb 100644 --- a/components/__tests__/ChipDistributionSummary.test.tsx +++ b/components/__tests__/ChipDistributionSummary.test.tsx @@ -2,6 +2,13 @@ import React from "react"; import { render } from "@testing-library/react-native"; import ChipDistributionSummary from "../ChipDistributionSummary"; +jest.mock("@expo/vector-icons", () => { + const { Text } = require("react-native"); + return { + MaterialIcons: () => TestIcon, + }; +}); + describe("ChipDistributionSummary Component", () => { test("renders correctly with valid data", () => { const playerCount = 4; diff --git a/i18n/en.json b/i18n/en.json index da31ef9..c7033e3 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -36,6 +36,7 @@ "failed_to_save_state": "Failed to save state.", "state_loaded_from": "State loaded from", "info": "Info", + "warning": "Warning", "no_saved_state_found": "No saved state found.", "automatic_chip_detection": "Automatic Chip Detection", "manual_chip_adjustment": "Manual Chip Adjustment", @@ -44,6 +45,7 @@ "save_slot_2": "Save\nSlot 2", "load_slot_1": "Load\nSlot 1", "load_slot_2": "Load\nSlot 2", - "please_select_valid_buyin": "Please select a valid buy-in amount" + "please_select_valid_buyin": "Please select a valid buy-in amount", + "chip_value_warn": "Be advised that the value of the distributed chips does not equal the buy-in for these inputs.\n\nHowever, results shown are fair to all players" } } diff --git a/i18n/es.json b/i18n/es.json index c39c4aa..6395e86 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -37,6 +37,7 @@ "failed_to_save_state": "No se pudo guardar el estado.", "state_loaded_from": "Estado cargado desde", "info": "Información", + "warning": "Advertencia", "no_saved_state_found": "No se encontró estado guardado.", "automatic_chip_detection": "Detección automática de fichas", "manual_chip_adjustment": "Ajuste manual de fichas", @@ -45,6 +46,7 @@ "save_slot_2": "Guardar\nSlot 2", "load_slot_1": "Cargar\nSlot 1", "load_slot_2": "Cargar\nSlot 2", - "please_select_valid_buyin": "Por favor seleccione una cantidad de buy-in válida" + "please_select_valid_buyin": "Por favor seleccione una cantidad de buy-in válida", + "chip_value_warn": "Tenga en cuenta que el valor de las fichas distribuidas no es igual al buy-in para estas entradas.\n\nSin embargo, los resultados que se muestran son justos para todos los jugadores." } } diff --git a/styles/styles.ts b/styles/styles.ts index 8ae1a57..dc5376f 100644 --- a/styles/styles.ts +++ b/styles/styles.ts @@ -5,7 +5,7 @@ export const COLORS = { SECONDARY: "#6c757d", SUCCESS: "#28a745", DANGER: "#dc3545", - WARNING: "#ffc107", + WARNING: "#c79c28", }; const lightStyles = StyleSheet.create({});