Major refactoring work to minimize tables in BridgeCompute class.
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project version="4"> |
| | | <component name="EntryPointsManager"> |
| | | <entry_points version="2.0" /> |
| | | </component> |
| | | <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK"> |
| | | <output url="file://$PROJECT_DIR$/classes" /> |
| | | </component> |
| | |
| | | <orderEntry type="library" exported="" name="appcompat-v7-21.0.3" level="project" /> |
| | | <orderEntry type="library" exported="" name="support-annotations-21.0.3" level="project" /> |
| | | <orderEntry type="library" exported="" name="support-v4-21.0.3" level="project" /> |
| | | <orderEntry type="module-library" scope="TEST"> |
| | | <library name="JUnit4"> |
| | | <CLASSES> |
| | | <root url="jar://$APPLICATION_HOME_DIR$/lib/junit-4.11.jar!/" /> |
| | | <root url="jar://$APPLICATION_HOME_DIR$/lib/hamcrest-core-1.3.jar!/" /> |
| | | <root url="jar://$APPLICATION_HOME_DIR$/lib/hamcrest-library-1.3.jar!/" /> |
| | | </CLASSES> |
| | | <JAVADOC /> |
| | | <SOURCES /> |
| | | </library> |
| | | </orderEntry> |
| | | </component> |
| | | </module> |
| | | |
| | |
| | | package net.jacekk.bridge; |
| | | |
| | | /** |
| | | * Created by jacek on 18.01.15. |
| | | */ |
| | | public class BridgeComputeTest { |
| | | import junit.framework.TestCase; |
| | | |
| | | public class BridgeComputeTest extends TestCase { |
| | | BridgeCompute compute = new BridgeCompute(); |
| | | BrydzLicz computeExpected = new BrydzLicz(); |
| | | |
| | | public void testGetIMPs() { |
| | | assertEquals(0, compute.getIMPs(0)); |
| | | assertEquals(0, compute.getIMPs(10)); |
| | | assertEquals(1, compute.getIMPs(20)); |
| | | assertEquals(1, compute.getIMPs(30)); |
| | | assertEquals(1, compute.getIMPs(40)); |
| | | assertEquals(2, compute.getIMPs(50)); |
| | | |
| | | assertEquals(23, compute.getIMPs(3999)); |
| | | assertEquals(24, compute.getIMPs(4000)); |
| | | assertEquals(24, compute.getIMPs(4001)); |
| | | } |
| | | |
| | | public void testGetPercent() { |
| | | assertEquals(50, compute.getPercent(20, 0, 0)); |
| | | assertEquals(44, compute.getPercent(21, 0, 0)); |
| | | } |
| | | |
| | | public void testGetResultForBasic() throws BridgeInputException { |
| | | BridgeInput input = new BridgeInput(); |
| | | input.bid = 0; |
| | | input.PC = 20; |
| | | input.weVulnerable = false; |
| | | input.theyVulnerable = false; |
| | | input.suit = BridgeInput.Suit.MINOR; |
| | | input.contract = BridgeInput.Contract.NORMAL; |
| | | BridgeResult result; |
| | | |
| | | result = compute.getResultForInput(input); |
| | | assertEquals(BridgeResult.Side.They, result.winners); |
| | | assertEquals(0, result.IMPs); |
| | | assertEquals(50, result.percent); |
| | | |
| | | input.PC = 21; |
| | | result = compute.getResultForInput(input); |
| | | assertEquals(BridgeResult.Side.They, result.winners); |
| | | assertEquals(2, result.IMPs); |
| | | assertEquals(56, result.percent); |
| | | |
| | | input.PC = 24; |
| | | result = compute.getResultForInput(input); |
| | | assertEquals(BridgeResult.Side.They, result.winners); |
| | | assertEquals(5, result.IMPs); |
| | | assertEquals(56, result.percent); |
| | | |
| | | input.PC = 25; |
| | | result = compute.getResultForInput(input); |
| | | assertEquals(BridgeResult.Side.They, result.winners); |
| | | assertEquals(7, result.IMPs); |
| | | assertEquals(74, result.percent); |
| | | } |
| | | |
| | | public void testGetResultForFull() throws BridgeInputException { |
| | | int contract; |
| | | int suit; |
| | | int game; |
| | | int vulnerability; |
| | | int PC; |
| | | int tricks; |
| | | BridgeInput input = new BridgeInput(); |
| | | BridgeResult result; |
| | | BrydzLicz.BrydzWynik expectedResult; |
| | | |
| | | for (contract = 0; contract <= 7; contract++) { |
| | | input.bid = contract; |
| | | for (suit = 0; suit <= 2; suit++) { |
| | | input.suit = BridgeInput.Suit.values()[suit]; |
| | | for (game = 0; game <= 2; game++) { |
| | | input.contract = BridgeInput.Contract.values()[game]; |
| | | for (vulnerability = 0; vulnerability <= 3; vulnerability++) { |
| | | input.weVulnerable = vulnerability / 2 >= 1; |
| | | input.theyVulnerable = vulnerability % 2 >= 1; |
| | | for (PC = 0; PC <= 40; PC++) { |
| | | input.PC = PC; |
| | | for (tricks = 0; tricks <= 13; tricks++) { |
| | | |
| | | input.tricks = tricks; |
| | | try { |
| | | result = compute.getResultForInput(input); |
| | | } catch (Exception e) { |
| | | if (contract > 0) { |
| | | throw e; |
| | | } |
| | | continue; |
| | | } |
| | | |
| | | expectedResult = computeExpected.policz(contract, suit, game, vulnerability, PC, tricks); |
| | | |
| | | assertEquals(input.toString(), expectedResult.dla, result.winners.ordinal()); |
| | | assertEquals(input.toString(), expectedResult.punkty_przed, result.pointsBefore); |
| | | assertEquals(input.toString(), expectedResult.punkty, result.points); |
| | | assertEquals(input.toString(), expectedResult.IMP, result.IMPs); |
| | | assertEquals(input.toString(), expectedResult.procent, result.percent); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | package net.jacekk.bridge; |
| | | |
| | | public class BrydzLicz { |
| | | public class BrydzWynik { |
| | | public int dla; |
| | | public int punkty_przed; |
| | | public int punkty; |
| | | public int IMP; |
| | | public int procent; |
| | | } |
| | | |
| | | protected int lewy[][] = { |
| | | {0, 20, 40, 60, 80, 100, 120, 140}, // młodsze |
| | | {0, 30, 60, 90, 120, 150, 180, 210}, // starsze |
| | |
| | | |
| | | protected int procenty_punkty[][] = { |
| | | {0, 50, 90, 120, 150, 180, 210, 300, 400, 430, 460, 490, 520, 800, 920, 940, 980, 990, 1020, 1400, 1440, 1520, 1530, 9999999}, // przed |
| | | {0, 50, 90, 120, 150, 180, 210, 500, 600, 360, 660, 690, 720, 810, 1370, 1390, 1430, 1440, 1470, 1700, 2000, 2220, 2230, 9999999} //po |
| | | {0, 50, 90, 120, 150, 180, 210, 500, 600, 630, 660, 690, 720, 810, 1370, 1390, 1430, 1440, 1470, 1700, 2000, 2220, 2230, 9999999} //po |
| | | }; |
| | | |
| | | protected int procenty_PC[] = {0, 6, 10, 16, 21, 25, 31, 35, 9999999}; |
| | |
| | | wynik_punkty = this.lewy[kolor][lewy - 6]; |
| | | } |
| | | // Kontra lub rekontra |
| | | else |
| | | { |
| | | else { |
| | | wynik_lewy = this.lewy[kolor][kontrakt] * mnoznik; |
| | | wynik_punkty = wynik_lewy; |
| | | |
| | |
| | | if(kontrakt == 6) { |
| | | // Za szlemika |
| | | wynik_punkty += (my_partia == 0 ? 500 : 750); |
| | | } |
| | | else if(kontrakt == 7) { |
| | | } else if (kontrakt == 7) { |
| | | // Za szlema |
| | | wynik_punkty += (my_partia == 0 ? 1000 : 1500); |
| | | } |
| | |
| | | if(wynik_lewy >= 100) { |
| | | // Za partię |
| | | wynik_punkty += (my_partia == 0 ? 300 : 500); |
| | | } |
| | | else |
| | | { |
| | | } else { |
| | | // Za częściówkę |
| | | wynik_punkty += 50; |
| | | } |
| | | } |
| | | // Wpadka |
| | | else |
| | | { |
| | | else { |
| | | // Punkty za wpadkę |
| | | wynik_punkty = -1 * this.wpadki[my_partia][kontra][-1 * nadrobki]; |
| | | } |
| | |
| | | wynik.IMP = IMP(wynik.punkty); |
| | | if( wynik_punkty < 0 ) { |
| | | wynik.procent = procenty(40 - PC, -1 * wynik_punkty, wy_partia); |
| | | } |
| | | else |
| | | { |
| | | } else { |
| | | wynik.procent = 100 - procenty(PC, wynik_punkty, my_partia); |
| | | } |
| | | } |
| | | // Zapis dla rozgrywających |
| | | else |
| | | { |
| | | else { |
| | | wynik.dla = 0; |
| | | wynik.punkty_przed = wynik_punkty; |
| | | wynik.punkty = wynik_punkty_PC; |
| | | wynik.IMP = IMP(wynik.punkty); |
| | | if( wynik_punkty > 0 ) { |
| | | wynik.procent = procenty(PC, wynik_punkty, my_partia); |
| | | } |
| | | else |
| | | { |
| | | } else { |
| | | wynik.procent = 100 - procenty(40 - PC, -1 * wynik_punkty, wy_partia); |
| | | } |
| | | } |
| | |
| | | package net.jacekk.bridge; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | public class BridgeCompute { |
| | | // Points for tricks |
| | | protected int tricks[][] = { |
| | | {0, 20, 40, 60, 80, 100, 120, 140}, // minor suits |
| | | {0, 30, 60, 90, 120, 150, 180, 210}, // major suits |
| | | {0, 40, 70, 100, 130, 160, 190, 220} // no trump |
| | | }; |
| | | |
| | | // Points for tricks (minor, major, no trump) |
| | | protected int tricks[] = {20, 30, 30}; |
| | | |
| | | // Points for [i] undertricks |
| | | protected int undertricks[][][] = { |
| | |
| | | } |
| | | }; |
| | | |
| | | // Points required per Milton Work Point Count |
| | | protected int PC[][][] = { |
| | | { // We: non vulnerable, they: non vulnerable |
| | | {-1400, -1400, -1400, -1400, -1200, -1100, -1000, -900, -700, -600, -490, |
| | | -460, -430, -400, -350, -300, -200, -110, -70, -50, 0, |
| | | 50, 70, 110, 200, 300, 350, 400, 430, 460, 490, |
| | | 600, 700, 900, 1000, 1100, 1200, 1400, 1400, 1400, 1400}, |
| | | // We: non vulnerable, they: vulnerable |
| | | {-2100, -2100, -2100, -2100, -1800, -1650, -1500, -1350, -1050, -800, -690, |
| | | -660, -630, -600, -520, -440, -290, -110, -70, -50, 0, |
| | | 50, 70, 110, 200, 300, 350, 400, 430, 460, 490, |
| | | 600, 700, 900, 1000, 1100, 1200, 1400, 1400, 1400, 1400} |
| | | // Points required per Milton Work Point Count (from 20 up) |
| | | protected int PC[][] = { |
| | | {0, 50, 70, 110, 200, 300, 350, 400, 430, 460, 490, 600, 700, 900, |
| | | 1000, 1100, 1200, 1400, 1400, 1400, 1400 |
| | | }, |
| | | { // We: vulnerable, they: non vulnerable |
| | | {-1400, -1400, -1400, -1400, -1200, -1100, -1000, -900, -700, -600, -490, |
| | | -460, -430, -400, -350, -300, -200, -110, -70, -50, 0, |
| | | 50, 70, 110, 290, 440, 520, 600, 630, 660, 690, |
| | | 800, 1050, 1350, 1500, 1650, 1800, 2100, 2100, 2100, 2100}, |
| | | // We: vulnerable, they: vulnerable |
| | | {-2100, -2100, -2100, -2100, -1800, -1650, -1500, -1350, -1050, -800, -690, |
| | | -660, -630, -600, -520, -440, -290, -110, -70, -50, 0, |
| | | 50, 70, 110, 290, 440, 520, 600, 630, 660, 690, |
| | | 800, 1050, 1350, 1500, 1650, 1800, 2100, 2100, 2100, 2100} |
| | | {0, 50, 70, 110, 290, 440, 520, 600, 630, 660, 690, 800, 1050, 1350, |
| | | 1500, 1650, 1800, 2100, 2100, 2100, 2100 |
| | | } |
| | | }; |
| | | |
| | |
| | | // See: http://www.gplewniak.republika.pl/strony/zapis.html |
| | | |
| | | // Points received - [i] used to access row from percent variable |
| | | protected int percent_points[][] = { |
| | | protected int percentPoints[][] = { |
| | | {0, 50, 90, 120, 150, 180, 210, 300, 400, 430, 460, 490, 520, 800, 920, 940, 980, 990, |
| | | 1020, 1400, 1440, 1520, 1530, 9999999}, // non vulnerable |
| | | {0, 50, 90, 120, 150, 180, 210, 500, 600, 360, 660, 690, 720, 810, 1370, 1390, 1430, |
| | | {0, 50, 90, 120, 150, 180, 210, 500, 600, 630, 660, 690, 720, 810, 1370, 1390, 1430, |
| | | 1440, 1470, 1700, 2000, 2220, 2230, 9999999} // vulnerable |
| | | }; |
| | | |
| | | // Work Point Count - [i] used to access column from property percent |
| | | protected int percent_PC[] = {0, 6, 10, 16, 21, 25, 31, 35, 9999999}; |
| | | protected int percentPCs[] = {0, 6, 10, 16, 21, 25, 31, 35, 9999999}; |
| | | |
| | | // Percent score per [i] - points scored, [j] - PC had |
| | | // Percent score per [i] - points scored, [j] - PCs had |
| | | protected int percent[][] = { |
| | | {-1, -1, -1, 50, 44, 26, 8, 0}, |
| | | {83, 74, 65, 56, 47, 29, 11, 0}, |
| | |
| | | }; |
| | | |
| | | // Finds IMP score for points given (using IMPs property) |
| | | protected int IMP(int points) { |
| | | int i = 0; |
| | | while (IMPs[i + 1] <= points) { |
| | | i++; |
| | | protected int getIMPs(int points) { |
| | | int position = Arrays.binarySearch(this.IMPs, points); |
| | | if (position < 0) { |
| | | return -position - 2; |
| | | } |
| | | return i; |
| | | return position; |
| | | } |
| | | |
| | | // Finds percent score for data given (using percent* properties) |
| | | protected int percent(int PC, int points, int vulnerability) { |
| | | int points_i = 0; |
| | | int PC_i = 0; |
| | | protected int getPercent(int PC, int points, int vulnerability) { |
| | | int positionPoints = Arrays.binarySearch(this.percentPoints[vulnerability], points); |
| | | int positionPCs = Arrays.binarySearch(this.percentPCs, PC); |
| | | if (positionPoints < 0) positionPoints = -positionPoints - 2; |
| | | if (positionPCs < 0) positionPCs = -positionPCs - 2; |
| | | |
| | | while (this.percent_points[vulnerability][points_i + 1] <= points) { |
| | | points_i++; |
| | | return this.percent[positionPoints][positionPCs]; |
| | | } |
| | | |
| | | while (this.percent_PC[PC_i + 1] <= PC) { |
| | | PC_i++; |
| | | public void validateInput(BridgeInput input) throws BridgeInputException { |
| | | if (input.bid < 0 || input.bid > 7) { |
| | | throw new BridgeInputException(BridgeInputException.Error.CONTRACT_LEVEL_INVALID); |
| | | } |
| | | |
| | | return this.percent[points_i][PC_i]; |
| | | if (input.suit == null) { |
| | | throw new BridgeInputException(BridgeInputException.Error.CONTRACT_SUIT_INVALID); |
| | | } |
| | | |
| | | public BridgeResult compute(int bid, int color, int dbl, int vulnerability, int PC, int tricks) { |
| | | if (input.contract == null) { |
| | | throw new BridgeInputException(BridgeInputException.Error.CONTRACT_DOUBLE_INVALID); |
| | | } |
| | | |
| | | if (input.PC < 0 || input.PC > 40) { |
| | | throw new BridgeInputException(BridgeInputException.Error.PC_INVALID); |
| | | } |
| | | |
| | | if (input.tricks < 0 || input.tricks > 13) { |
| | | throw new BridgeInputException(BridgeInputException.Error.TRICKS_INVALID); |
| | | } |
| | | |
| | | if (input.bid == 0 && input.PC < 20) { |
| | | throw new BridgeInputException(BridgeInputException.Error.PASSES_INVALID); |
| | | } |
| | | } |
| | | |
| | | public BridgeResult getResultForInput(BridgeInput input) throws BridgeInputException { |
| | | validateInput(input); |
| | | |
| | | int weVulnerable = (input.weVulnerable) ? 1 : 0; |
| | | int theyVulnerable = (input.theyVulnerable) ? 1 : 0; |
| | | int bid = input.bid; |
| | | |
| | | BridgeResult result = new BridgeResult(); |
| | | int weVulnerable = vulnerability / 2; |
| | | int theyVulnerable = vulnerability % 2; |
| | | |
| | | // 4 passes |
| | | if (bid == 0) { |
| | | result.pointsFor = BridgeResult.PointsFor.Them; |
| | | result.points = this.PC[weVulnerable][theyVulnerable][PC]; |
| | | result.IMPs = this.IMP(result.points); |
| | | result.percent = 100 - this.percent(PC, 0, weVulnerable); |
| | | |
| | | if (input.bid == 0) { |
| | | result.winners = BridgeResult.Side.They; |
| | | result.points = this.PC[weVulnerable][input.PC - 20]; |
| | | result.IMPs = this.getIMPs(result.points); |
| | | result.percent = 100 - this.getPercent(input.PC, 0, weVulnerable); |
| | | return result; |
| | | } |
| | | |
| | | |
| | | int multiplier = input.contract.multiplier; |
| | | int dbl = input.contract.tableIndex; |
| | | int tricks = input.tricks; |
| | | |
| | | // Result in points |
| | | int resultPoints; |
| | | // Points for tricks |
| | | int pointsForTricks; |
| | | int points; |
| | | // Points for tricks bid |
| | | int pointsForTricksBid; |
| | | // Result minus points required, according to PC property |
| | | int pointsForScoring; |
| | | |
| | | // Number of overtricks (or undertricks if negative) |
| | | int additionalTricks = tricks - 6 - bid; |
| | | |
| | | // Double/redouble multiplier |
| | | int multiplier = dbl + 1; |
| | | if (multiplier == 3) { |
| | | multiplier = 4; |
| | | } |
| | | |
| | | // Contract made |
| | | if (additionalTricks >= 0) { |
| | | pointsForTricksBid = this.tricks[input.suit.tableIndex] * bid * multiplier; |
| | | if (input.suit.equals(BridgeInput.Suit.NOTRUMP)) { |
| | | // First trick in no trump game is worth 10 points more |
| | | pointsForTricksBid += 10 * multiplier; |
| | | } |
| | | points = pointsForTricksBid; |
| | | |
| | | // Add points for overtricks |
| | | |
| | | // Ordinary contract |
| | | if (multiplier == 1) { |
| | | pointsForTricks = this.tricks[color][bid]; |
| | | resultPoints = this.tricks[color][tricks - 6]; |
| | | if (input.contract.equals(BridgeInput.Contract.NORMAL)) { |
| | | points += this.tricks[input.suit.tableIndex] * additionalTricks; |
| | | } |
| | | // Contract doubled/redoubled |
| | | else { |
| | | pointsForTricks = this.tricks[color][bid] * multiplier; |
| | | resultPoints = pointsForTricks; |
| | | points += (!input.weVulnerable ? 50 : 100) * multiplier * additionalTricks; |
| | | |
| | | // Bonus for winning doubled/redoubled contract |
| | | resultPoints += 25 * multiplier; |
| | | // For overtricks |
| | | resultPoints += additionalTricks * (weVulnerable == 0 ? 50 : 100) * multiplier; |
| | | points += 25 * multiplier; |
| | | } |
| | | |
| | | if (bid == 6) { |
| | | // Bonus for small slam |
| | | resultPoints += (weVulnerable == 0 ? 500 : 750); |
| | | points += (!input.weVulnerable ? 500 : 750); |
| | | } else if (bid == 7) { |
| | | // Bonus for grand slam |
| | | resultPoints += (weVulnerable == 0 ? 1000 : 1500); |
| | | points += (!input.weVulnerable ? 1000 : 1500); |
| | | } |
| | | |
| | | if (pointsForTricks >= 100) { |
| | | if (pointsForTricksBid >= 100) { |
| | | // Bonus for game |
| | | resultPoints += (weVulnerable == 0 ? 300 : 500); |
| | | points += (!input.weVulnerable ? 300 : 500); |
| | | } else { |
| | | // Bonus for part-game |
| | | resultPoints += 50; |
| | | points += 50; |
| | | } |
| | | } |
| | | // Contract defeated |
| | | else { |
| | | // Points for undertricks (for defending side) |
| | | resultPoints = -1 * this.undertricks[weVulnerable][dbl][-1 * additionalTricks]; |
| | | points = -1 * this.undertricks[weVulnerable][dbl][-1 * additionalTricks]; |
| | | } |
| | | |
| | | // Deduct points required |
| | | pointsForScoring = resultPoints - this.PC[weVulnerable][theyVulnerable][PC]; |
| | | if (input.PC >= 20) { |
| | | pointsForScoring = points - this.PC[weVulnerable][input.PC - 20]; |
| | | } else { |
| | | pointsForScoring = points + this.PC[theyVulnerable][20 - input.PC]; |
| | | } |
| | | |
| | | // Score for defeaters |
| | | if (pointsForScoring < 0) { |
| | | result.pointsFor = BridgeResult.PointsFor.Them; |
| | | result.pointsBefore = -1 * resultPoints; |
| | | result.winners = BridgeResult.Side.They; |
| | | result.pointsBefore = -1 * points; |
| | | result.points = -1 * pointsForScoring; |
| | | result.IMPs = IMP(result.points); |
| | | if (resultPoints < 0) { |
| | | result.percent = percent(40 - PC, -1 * resultPoints, theyVulnerable); |
| | | |
| | | if (points < 0) { |
| | | result.percent = getPercent(40 - input.PC, -points, theyVulnerable); |
| | | } else { |
| | | result.percent = 100 - percent(PC, resultPoints, weVulnerable); |
| | | result.percent = 100 - getPercent(input.PC, points, weVulnerable); |
| | | } |
| | | } |
| | | // Score for declarers |
| | | else { |
| | | result.pointsFor = BridgeResult.PointsFor.Us; |
| | | result.pointsBefore = resultPoints; |
| | | result.winners = BridgeResult.Side.We; |
| | | result.pointsBefore = points; |
| | | result.points = pointsForScoring; |
| | | result.IMPs = IMP(result.points); |
| | | if (resultPoints > 0) { |
| | | result.percent = percent(PC, resultPoints, weVulnerable); |
| | | |
| | | if (points > 0) { |
| | | result.percent = getPercent(input.PC, points, weVulnerable); |
| | | } else { |
| | | result.percent = 100 - percent(40 - PC, -1 * resultPoints, theyVulnerable); |
| | | result.percent = 100 - getPercent(40 - input.PC, -points, theyVulnerable); |
| | | } |
| | | } |
| | | |
| | | result.IMPs = getIMPs(result.points); |
| | | |
| | | |
| | | return result; |
| | | } |
| | | } |
| | |
| | | package net.jacekk.bridge; |
| | | |
| | | /** |
| | | * Created by jacek on 18.01.15. |
| | | */ |
| | | public class BridgeInput { |
| | | public enum Suit { |
| | | MINOR(0), MAJOR(1), NOTRUMP(2); |
| | | |
| | | public final int tableIndex; |
| | | |
| | | Suit(int tableIndex) { |
| | | this.tableIndex = tableIndex; |
| | | } |
| | | } |
| | | |
| | | public enum Contract { |
| | | NORMAL(1, 0), DOUBLED(2, 1), REDOUBLED(4, 2); |
| | | |
| | | public final int multiplier; |
| | | public final int tableIndex; |
| | | |
| | | Contract(int multiplier, int tableIndex) { |
| | | this.multiplier = multiplier; |
| | | this.tableIndex = tableIndex; |
| | | } |
| | | } |
| | | |
| | | public int bid; |
| | | public Suit suit; |
| | | public Contract contract; |
| | | public boolean weVulnerable; |
| | | public boolean theyVulnerable; |
| | | public int PC; |
| | | public int tricks; |
| | | |
| | | public String toString() { |
| | | StringBuilder builder = new StringBuilder(); |
| | | builder.append(bid).append(' ').append(suit.name()).append(' '); |
| | | builder.append(contract.name()).append(' '); |
| | | |
| | | if (weVulnerable) |
| | | builder.append('V'); |
| | | else |
| | | builder.append('N'); |
| | | if (theyVulnerable) |
| | | builder.append('V'); |
| | | else |
| | | builder.append('N'); |
| | | builder.append(' '); |
| | | builder.append(PC).append("PC, tricks: ").append(tricks); |
| | | return builder.toString(); |
| | | } |
| | | } |
| | |
| | | package net.jacekk.bridge; |
| | | |
| | | /** |
| | | * Created by jacek on 18.01.15. |
| | | */ |
| | | public class BridgeInputException { |
| | | public class BridgeInputException extends Exception { |
| | | public enum Error { |
| | | CONTRACT_LEVEL_INVALID, CONTRACT_SUIT_INVALID, |
| | | CONTRACT_DOUBLE_INVALID, PC_INVALID, |
| | | TRICKS_INVALID, PASSES_INVALID |
| | | } |
| | | |
| | | final Error error; |
| | | |
| | | public BridgeInputException(Error error) { |
| | | this.error = error; |
| | | } |
| | | |
| | | public Error getError() { |
| | | return error; |
| | | } |
| | | } |
| | |
| | | package net.jacekk.bridge; |
| | | |
| | | public class BridgeResult { |
| | | public enum PointsFor { |
| | | Us, Them |
| | | public enum Side { |
| | | We, They |
| | | } |
| | | |
| | | public PointsFor pointsFor; |
| | | public Side winners; |
| | | public int pointsBefore; |
| | | public int points; |
| | | public int IMPs; |
| | |
| | | package net.jacekk.bridge.android; |
| | | |
| | | /** |
| | | * Created by jacek on 18.01.15. |
| | | */ |
| | | import net.jacekk.bridge.BridgeInputException; |
| | | import net.jacekk.bridge.R; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | public class BridgeInputExceptionMapper { |
| | | public static final Map<BridgeInputException.Error, Integer> errorMap; |
| | | |
| | | static { |
| | | errorMap = new HashMap<>(); |
| | | errorMap.put(BridgeInputException.Error.CONTRACT_LEVEL_INVALID, R.string.invalid_level); |
| | | errorMap.put(BridgeInputException.Error.CONTRACT_SUIT_INVALID, R.string.invalid_color); |
| | | errorMap.put(BridgeInputException.Error.CONTRACT_DOUBLE_INVALID, R.string.invalid_contract); |
| | | errorMap.put(BridgeInputException.Error.PC_INVALID, R.string.invalid_pc); |
| | | errorMap.put(BridgeInputException.Error.TRICKS_INVALID, R.string.invalid_tricks); |
| | | errorMap.put(BridgeInputException.Error.PASSES_INVALID, R.string.invalid_passes); |
| | | } |
| | | |
| | | public static int map(BridgeInputException e) { |
| | | return errorMap.get(e.getError()); |
| | | } |
| | | } |
| | |
| | | import android.widget.TextView; |
| | | import android.widget.ToggleButton; |
| | | |
| | | import net.jacekk.bridge.R; |
| | | import net.jacekk.bridge.BridgeCompute; |
| | | import net.jacekk.bridge.BridgeInput; |
| | | import net.jacekk.bridge.BridgeInputException; |
| | | import net.jacekk.bridge.BridgeResult; |
| | | import net.jacekk.bridge.R; |
| | | |
| | | public class MainActivity extends Activity { |
| | | private SeekBar BidSlider; |
| | |
| | | private EditText PCInput; |
| | | private EditText TricksInput; |
| | | |
| | | private TextView resultText; |
| | | private TextView ResultsText; |
| | | |
| | | public BridgeCompute bridgeCompute; |
| | | |
| | |
| | | InitializeApp(); |
| | | } |
| | | |
| | | @Override |
| | | public void onBackPressed() { |
| | | // Reset |
| | | private void resetInputs() { |
| | | BidSlider.setProgress(0); |
| | | MinorSuitsToggle.setChecked(true); |
| | | ContractToggle.setChecked(true); |
| | | NNToggle.setChecked(true); |
| | | PCInput.setText(""); |
| | | TricksInput.setText(""); |
| | | ResultsText.setText(getString(R.string.enter_data)); |
| | | } |
| | | |
| | | private void InitializeApp() { |
| | |
| | | PCInput = (EditText) findViewById(R.id.PCInput); |
| | | TricksInput = (EditText) findViewById(R.id.TricksInput); |
| | | |
| | | resultText = (TextView) findViewById(R.id.ResultsText); |
| | | ResultsText = (TextView) findViewById(R.id.ResultsText); |
| | | |
| | | CompoundButton.OnCheckedChangeListener changeListener; |
| | | |
| | |
| | | } |
| | | |
| | | public void updateResults() { |
| | | BridgeInput input = getBridgeInput(); |
| | | |
| | | BridgeResult result; |
| | | try { |
| | | result = bridgeCompute.getResultForInput(input); |
| | | } catch (BridgeInputException e) { |
| | | int errorStringId = BridgeInputExceptionMapper.map(e); |
| | | ResultsText.setText(getString(errorStringId)); |
| | | return; |
| | | } |
| | | |
| | | ResultsText.setText( |
| | | (result.winners == BridgeResult.Side.We ? getString(R.string.result_for_us) |
| | | : getString(R.string.result_for_them)) + |
| | | "\n" + getString(R.string.result_pts_wo_pc) + " " + result.pointsBefore + |
| | | "\n" + getString(R.string.result_pts) + " " + result.points + |
| | | "\n" + getString(R.string.result_imps) + " " + result.IMPs + |
| | | "\n" + getString(R.string.result_percent) + " " + result.percent); |
| | | } |
| | | |
| | | private BridgeInput getBridgeInput() { |
| | | int bid = BidSlider.getProgress(); |
| | | |
| | | int color = 0; |
| | |
| | | } catch (NumberFormatException ignored) { |
| | | } |
| | | |
| | | if (bid < 0 || bid > 7) { |
| | | resultText.setText(getString(R.string.invalid_bid)); |
| | | return; |
| | | } |
| | | |
| | | if (color != 0 && color != 1 && color != 2) { |
| | | resultText.setText(getString(R.string.invalid_color)); |
| | | return; |
| | | } |
| | | |
| | | if (dbl < 0 || dbl > 2) { |
| | | resultText.setText(getString(R.string.invalid_dbl)); |
| | | return; |
| | | } |
| | | |
| | | if (vulnerability < 0 || vulnerability > 3) { |
| | | resultText.setText(getString(R.string.invalid_baba)); |
| | | return; |
| | | } |
| | | |
| | | if (PC < 0 || PC > 40) { |
| | | resultText.setText(getString(R.string.invalid_pc)); |
| | | return; |
| | | } |
| | | |
| | | if (tricks < 0 || tricks > 13) { |
| | | resultText.setText(getString(R.string.invalid_tricks)); |
| | | return; |
| | | } |
| | | |
| | | if (bid == 0 && PC < 20) { |
| | | resultText.setText(getString(R.string.invalid_pass)); |
| | | return; |
| | | } |
| | | |
| | | BridgeResult result = bridgeCompute.compute(bid, color, dbl, vulnerability, PC, tricks); |
| | | resultText.setText( |
| | | (result.pointsFor == BridgeResult.PointsFor.Us ? getString(R.string.result_for_us) : getString(R.string.result_for_them)) + |
| | | "\n" + getString(R.string.result_pts_wo_pc) + " " + result.pointsBefore + |
| | | "\n" + getString(R.string.result_pts) + " " + result.points + |
| | | "\n" + getString(R.string.result_imps) + " " + result.IMPs + |
| | | "\n" + getString(R.string.result_percent) + " " + result.percent); |
| | | BridgeInput input = new BridgeInput(); |
| | | input.bid = bid; |
| | | input.suit = BridgeInput.Suit.values()[color]; |
| | | input.contract = BridgeInput.Contract.values()[dbl]; |
| | | input.weVulnerable = vulnerability / 2 >= 1; |
| | | input.theyVulnerable = vulnerability % 2 >= 1; |
| | | input.PC = PC; |
| | | input.tricks = tricks; |
| | | return input; |
| | | } |
| | | } |
| | |
| | | android:layout_height="wrap_content" |
| | | android:layout_weight="0.25" |
| | | android:checked="false" |
| | | android:text="@string/no_trumph" |
| | | android:textOff="@string/no_trumph" |
| | | android:textOn="@string/no_trumph" /> |
| | | android:text="@string/no_trump" |
| | | android:textOff="@string/no_trump" |
| | | android:textOn="@string/no_trump" /> |
| | | </LinearLayout> |
| | | |
| | | <LinearLayout |
| | |
| | | android:layout_width="match_parent" |
| | | android:layout_height="match_parent" |
| | | android:layout_marginTop="10dp" |
| | | android:text="@string/invalid_empty" |
| | | android:text="@string/enter_data" |
| | | android:textAppearance="?android:attr/textAppearanceMedium" /> |
| | | </LinearLayout> |
| | | |
| | |
| | | |
| | | <string name="minor_suits">♣ / ♦</string> |
| | | <string name="major_suits">♥ / ♠</string> |
| | | <string name="no_trumph">NT</string> |
| | | <string name="no_trump">NT</string> |
| | | |
| | | <string name="before_before">przed/przed</string> |
| | | <string name="before_after">przed/po</string> |
| | |
| | | <string name="pc">PC:</string> |
| | | <string name="tricks">Lew:</string> |
| | | |
| | | <string name="invalid_empty">Podaj wszystkie dane.</string> |
| | | <string name="invalid_bid">Niepoprawny kontrakt.</string> |
| | | <string name="enter_data">Podaj wszystkie dane.</string> |
| | | <string name="invalid_level">Niepoprawny kontrakt.</string> |
| | | <string name="invalid_color">Niepoprawny kolor kontraktu.</string> |
| | | <string name="invalid_dbl">Niepoprawna informacja o kontrze.</string> |
| | | <string name="invalid_baba">Niepoprawna informacja o partii.</string> |
| | | <string name="invalid_contract">Niepoprawna informacja o kontrze.</string> |
| | | <string name="invalid_vulnerability">Niepoprawna informacja o partii.</string> |
| | | <string name="invalid_pc">Niepoprawna ilość punktów.</string> |
| | | <string name="invalid_tricks">Niepoprawna ilość wziętych lew.</string> |
| | | <string name="invalid_pass">Przy czterech pasach podaj większą liczę punktów.</string> |
| | | <string name="invalid_passes">Przy czterech pasach podaj większą liczę punktów.</string> |
| | | |
| | | <string name="result_for_us">Zapis dla rozgrywających.</string> |
| | | <string name="result_for_them">Zapis dla przeciwników.</string> |
| | |
| | | |
| | | <string name="minor_suits">♣ / ♦</string> |
| | | <string name="major_suits">♥ / ♠</string> |
| | | <string name="no_trumph">NT</string> |
| | | <string name="no_trump">NT</string> |
| | | |
| | | <string name="before_before">non./non</string> |
| | | <string name="before_after">non./vuln.</string> |
| | | <string name="after_before">vunl./non.</string> |
| | | <string name="after_before">vuln./non.</string> |
| | | <string name="after_after">vuln./vuln.</string> |
| | | |
| | | <string name="bid_normal">norm.</string> |
| | |
| | | <string name="pc">PC:</string> |
| | | <string name="tricks">Tricks:</string> |
| | | |
| | | <string name="invalid_empty">Enter required information.</string> |
| | | <string name="invalid_bid">Invalid contract level.</string> |
| | | <string name="enter_data">Enter required information.</string> |
| | | <string name="invalid_level">Invalid contract level.</string> |
| | | <string name="invalid_color">Invalid contract color.</string> |
| | | <string name="invalid_dbl">Invalid information about doubling/redoubling.</string> |
| | | <string name="invalid_baba">Invalid information about vulnerability.</string> |
| | | <string name="invalid_contract">Invalid information about doubling/redoubling.</string> |
| | | <string name="invalid_vulnerability">Invalid information about vulnerability.</string> |
| | | <string name="invalid_pc">Invalid number for Milton Work Point Count.</string> |
| | | <string name="invalid_tricks">Invalid number of tricks taken.</string> |
| | | <string name="invalid_pass">For four passes enter data for side with more PCs.</string> |
| | | <string name="invalid_passes">For four passes enter data for side with more PCs.</string> |
| | | |
| | | <string name="result_for_us">Score for declaring side.</string> |
| | | <string name="result_for_them">Score for defending side.</string> |