salliere-0.10/0000755000175000017500000000000011327153101011674 5ustar mjj29mjj29salliere-0.10/Makefile0000644000175000017500000001314111134734605013346 0ustar mjj29mjj29JAVA?=java JAVAC?=javac JAVADOC?=javadoc JAR?=jar GCJ?=gcj CC?=gcc LD?=ld GCJFLAGS?=-fjni JCFLAGS?=-source 1.5 -Xlint:all MSGFMT?=msgfmt PREFIX?=/usr/local JARLIBDIR?=$(PREFIX)/share/java JARINSTALLDIR?=$(PREFIX)/share/salliere DOCDIR?=$(PREFIX)/share/doc/salliere MANDIR?=$(PREFIX)/share/man/man1 SHAREDIR?=$(PREFIX)/share/salliere BINDIR?=$(PREFIX)/bin DEBUG?=disable CLASSPATH=$(JARLIBDIR)/csv.jar:$(JARLIBDIR)/debug-$(DEBUG).jar:$(JARLIBDIR)/itext.jar:$(JARLIBDIR)/commons-net.jar VERSION=$(shell sed -n '1s/Version \(.*\):/\1/p' changelog) SRC=$(shell find cx -name '*.java') all: salliere-$(VERSION).jar salliere.1 bin/salliere gsalliere-$(VERSION).jar gsalliere.1 bin/gsalliere bin/leaderboard leaderboard-$(VERSION).jar leaderboard.1 bin/ecl2salliere .bin: mkdir -p bin touch .bin .testbin: mkdir -p testbin touch .testbin classes: .classes .classes: $(SRC) translations/*.po mkdir -p classes $(JAVAC) $(JCFLAGS) -cp $(CLASSPATH):classes -d classes $(SRC) (cd translations; for i in *.po; do $(MSGFMT) --java2 -r salliere_localized -d ../classes -l $${i%.po} $$i; done) $(MSGFMT) --java2 -r salliere_localized -d classes translations/en_GB.po touch .classes clean: rm -rf classes bin testbin salliere-$(VERSION) rm -f .classes .bin .testbin *.tar.gz *.jar *.1 *Manifest.txt salliere-$(VERSION).jar: SalliereManifest.txt .classes (cd classes; $(JAR) cfm ../$@ ../$< $(shell cd classes; find cx -name '*.class' -and -not -name 'GSalliere*' -and -not -name 'Leader*' | sed 's/\$$/\\$$/g') *localized*.class) gsalliere-$(VERSION).jar: GSalliereManifest.txt .classes (cd classes; $(JAR) cfm ../$@ ../$< cx/ath/matthew/salliere/GSalliere*.class) leaderboard-$(VERSION).jar: LeaderBoardManifest.txt .classes (cd classes; $(JAR) cfm ../$@ ../$< cx/ath/matthew/salliere/Leader*.class) salliere-$(VERSION).tar.gz: Makefile cx README INSTALL COPYING changelog todo salliere.sh salliere.sgml Manifest.txt.in gsalliere.sh gsalliere.sgml translations ecl2salliere.sh leaderboard.sh leaderboard.sgml mkdir -p salliere-$(VERSION) cp -a $^ salliere-$(VERSION) tar zcf $@ salliere-$(VERSION) csv.jar: ln -sf /usr/share/java/csv.jar . itext.jar: ln -sf /usr/share/java/itext.jar . commons-net.jar: ln -sf /usr/share/java/commons-net.jar . debug-$(DEBUG).jar: ln -sf /usr/share/java/debug-$(DEBUG).jar . bin/%: %.sh .bin sed 's,\%JARINSTPATH\%,$(JARINSTALLDIR),;s,\%JARLIBPATH\%,$(JARLIBDIR),;s,\%VERSION\%,$(VERSION),;s,\%DEBUG\%,$(DEBUG),;s,\%JAVA\%,$(JAVA),' < $< > $@ testbin/%: %.sh .testbin salliere-$(VERSION).jar csv.jar debug-$(DEBUG).jar itext.jar gsalliere-$(VERSION).jar commons-net.jar leaderboard-$(VERSION).jar sed 's,\%JARPATH\%,.,;s,\%VERSION\%,$(VERSION),;s,\%DEBUG\%,$(DEBUG),;s,\%JAVA\%,$(JAVA),' < $< > $@ chmod 755 $@ %.1: %.sgml docbook-to-man $< > $@ SalliereManifest.txt: Manifest.txt.in echo Main-Class: cx.ath.matthew.salliere.Salliere > $@ ifeq ($(DEBUG),enable) echo Class-Path: $(JARLIBDIR)/csv.jar $(JARLIBDIR)/debug-$(DEBUG).jar $(JARLIBDIR)/itext.jar $(JARLIBDIR)/commons-net.jar >> $@ else echo Class-Path: $(JARLIBDIR)/csv.jar $(JARLIBDIR)/itext.jar $(JARLIBDIR)/commons-net.jar >> $@ endif cat $< >> $@ echo "Implementation-Version: $(VERSION)" >> $@ GSalliereManifest.txt: Manifest.txt.in echo Main-Class: cx.ath.matthew.salliere.GSalliere > $@ ifeq ($(DEBUG),enable) echo Class-Path: $(JARLIBDIR)/debug-$(DEBUG).jar $(JARINSTALLDIR)/salliere-$(VERSION).jar >> $@ else echo Class-Path: $(JARINSTALLDIR)/salliere-$(VERSION).jar >> $@ endif cat $< >> $@ echo "Implementation-Version: $(VERSION)" >> $@ LeaderBoardManifest.txt: Manifest.txt.in echo Main-Class: cx.ath.matthew.salliere.Leaders > $@ ifeq ($(DEBUG),enable) echo Class-Path: $(JARLIBDIR)/debug-$(DEBUG).jar $(JARINSTALLDIR)/salliere-$(VERSION).jar >> $@ else echo Class-Path: $(JARINSTALLDIR)/salliere-$(VERSION).jar >> $@ endif cat $< >> $@ echo "Implementation-Version: $(VERSION)" >> $@ translations/en_GB.po: $(SRC) echo "#java-format" > $@ sed -n '/_(/s/.*_("\([^"]*\)").*/\1/p' $^ | sort -u | sed 's/\(.*\)/msgid "\1"\nmsgstr "\1"/' >> $@ install: salliere.1 gsalliere.1 bin/salliere bin/gsalliere gsalliere-$(VERSION).jar salliere-$(VERSION).jar changelog COPYING INSTALL README todo bin/ecl2salliere bin/leaderboard leaderboard-$(VERSION).jar leaderboard.1 install -d $(DESTDIR)$(BINDIR) install bin/salliere $(DESTDIR)$(BINDIR) install bin/gsalliere $(DESTDIR)$(BINDIR) install bin/leaderboard $(DESTDIR)$(BINDIR) install bin/ecl2salliere $(DESTDIR)$(BINDIR) install -d $(DESTDIR)$(MANDIR) install -m 644 salliere.1 $(DESTDIR)$(MANDIR) install -m 644 leaderboard.1 $(DESTDIR)$(MANDIR) install -m 644 gsalliere.1 $(DESTDIR)$(MANDIR) install -d $(DESTDIR)$(JARINSTALLDIR) install -m 644 salliere-$(VERSION).jar $(DESTDIR)$(JARINSTALLDIR) install -m 644 gsalliere-$(VERSION).jar $(DESTDIR)$(JARINSTALLDIR) install -m 644 leaderboard-$(VERSION).jar $(DESTDIR)$(JARINSTALLDIR) install -d $(DESTDIR)$(DOCDIR) install -m 644 changelog COPYING INSTALL README todo $(DESTDIR)$(DOCDIR) uninstall: rm -f $(DESTDIR)$(BINDIR)/salliere $(DESTDIR)$(BINDIR)/gsalliere $(DESTDIR)$(BINDIR)/ecl2salliere $(DESTDIR)$(BINDIR)/leaderboard rm -f $(DESTDIR)$(JARINSTALLDIR)/salliere-$(VERSION).jar $(DESTDIR)$(JARINSTALLDIR)/gsalliere-$(VERSION).jar $(DESTDIR)$(JARINSTALLDIR)/leaderboard-$(VERSION).jar rm -f $(DESTDIR)$(MANDIR)/salliere.1 $(DESTDIR)$(MANDIR)/gsalliere.1 $(DESTDIR)$(MANDIR)/leaderboard.1 rm -f $(DESTDIR)$(DOCDIR)/changelog $(DESTDIR)$(DOCDIR)/COPYING $(DESTDIR)$(DOCDIR)/INSTALL $(DESTDIR)$(DOCDIR)/README $(DESTDIR)$(DOCDIR)/todo rmdir --ignore-fail-on-non-empty $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR) $(DESTDIR)$(JARINSTALLDIR) $(DESTDIR)$(DOCDIR) salliere-0.10/cx/0000755000175000017500000000000011134734605012320 5ustar mjj29mjj29salliere-0.10/cx/ath/0000755000175000017500000000000011134734605013074 5ustar mjj29mjj29salliere-0.10/cx/ath/matthew/0000755000175000017500000000000011134734605014545 5ustar mjj29mjj29salliere-0.10/cx/ath/matthew/salliere/0000755000175000017500000000000011327150633016342 5ustar mjj29mjj29salliere-0.10/cx/ath/matthew/salliere/AsciiTablePrinter.java0000644000175000017500000000504311134734605022556 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import cx.ath.matthew.debug.Debug; import java.io.PrintStream; import java.util.Arrays; public class AsciiTablePrinter implements TablePrinter { private PrintStream output; public AsciiTablePrinter(PrintStream output) { this.output = output; } public void print(String[] headers, String[][] rows) { if (Debug.debug) Debug.print(Debug.DEBUG, "printing "+Arrays.deepToString(rows)); // calculate column width int[] widths = new int[headers.length]; for (int i = 0; i < headers.length; i++) widths[i] = headers[i].length(); for (int i = 0; i < rows.length; i++) for (int j = 0; j < rows[i].length; j++) if (widths[j] < rows[i][j].length()) widths[j] = rows[i][j].length(); // gap for (int i = 0; i < widths.length; i++) widths[i]++; // print headers for (int i = 0; i < headers.length; i++) { output.print(headers[i]); for (int j = headers[i].length(); j < widths[i]; j++) output.print(' '); } output.println(); // print line for (int i = 0; i < widths.length; i++) for (int j = 0; j < widths[i]; j++) output.print('-'); output.println(); // print rows for (int i = 0; i < rows.length; i++) { for (int j = 0; j < rows[i].length; j++) { output.print(rows[i][j]); for (int k = rows[i][j].length(); k < widths[j]; k++) output.print(' '); } output.println(); } output.flush(); } public void header(String header) { output.println(header); } public void gap() { output.println(); } public void init() {} public void close() {} } salliere-0.10/cx/ath/matthew/salliere/Contract.java0000644000175000017500000002126511134734605020773 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import cx.ath.matthew.debug.Debug; import static cx.ath.matthew.salliere.Gettext._; import java.text.MessageFormat; public class Contract { public static final int NONE = 0; public static final int NORTH = 1; public static final int EAST = 2; public static final int ALL = 3; double nsscore; double ewscore; int tricks; String contract; char declarer; boolean beer; public Contract(String contract, char declarer, int vulnerability, int tricks) throws ContractParseException, NoContractException { if (Debug.debug) Debug.print("contract: "+contract+", declarer: "+declarer+", vulnerability: "+vulnerability+", tricks: "+tricks); char[] cs = contract.toCharArray(); if (cs.length == 0) throw new NoContractException(); int val = 0; char den = ' '; int doubled = 1; switch (declarer) { case 'n': declarer = 'N'; break; case 's': declarer = 'S'; break; case 'e': declarer = 'E'; break; case 'w': declarer = 'W'; break; } this.declarer = declarer; for (int i = 0; i < cs.length; i++) { switch (cs[i]) { case ' ': continue; case '1': case '2': case '3': case '4': case '5': case '6': case '7': val = (cs[i] - '0'); if (Debug.debug) Debug.print("cs["+i+"] = "+cs[i]+", val = "+val); continue; case 'H': case 'C': case 'D': case 'S': case 'N': case 'P': den = cs[i]; continue; case 'h': den = 'H'; continue; case 'c': den = 'C'; continue; case 'd': den = 'D'; continue; case 's': den = 'S'; continue; case 'n': case 't': case 'T': den = 'N'; continue; case 'p': case 'o': case 'O': case '.': den = 'P'; continue; case 'X': case 'x': doubled*=2; continue; case '=': tricks = 6+val; continue; case '-': case '+': StringBuilder sb = new StringBuilder(); int j; for (j = i+1; j < cs.length && cs[j] >= '0' && cs[j] <= '9'; j++) sb.append(cs[j]); if (sb.length() == 0) continue; int diff = Integer.parseInt(sb.toString()); if ('+' == cs[i]) tricks = 6+val+diff; else tricks = 6+val-diff; i = j-1; continue; case 'B': case 'b': case 'E': case 'e': case 'R': case 'r': beer = true; continue; default: throw new ContractParseException(MessageFormat.format(_("Symbol: {0} not allowed in contract"), new Object[] { cs[i] })); } } if (den == 'P') { // pass out board if (Debug.debug) Debug.print("Pass out"); this.nsscore = 0; this.ewscore = 0; this.tricks = 0; this.contract = "P.O."; return; } if (val < 1 || val > 7) throw new ContractParseException(_("Value must be between 1 & 7")); if (den == ' ') throw new ContractParseException(_("No denomination specified in contract")); if (doubled > 4) throw new ContractParseException(_("Cannot re-re-double contracts!")); if (Debug.debug) Debug.print(""+val+den+(1= (val+6)) { if (Debug.debug) Debug.print("MADE"); // NT bonus if ('N' == den) score += 10*doubled; if (Debug.debug) Debug.print(score); // trick score int ts = 0; switch (den) { case 'C': case 'D': ts = 20; break; default: ts = 30; break; } score += ts*val*doubled; if (Debug.debug) Debug.print(score); // partscore/game bonus if (score < 100) score += 50; else if (vul) score += 500; else score += 300; if (Debug.debug) Debug.print(score); // double bonus if (2 == doubled) score += 50; // redouble bonus else if (4 == doubled) score += 100; if (Debug.debug) Debug.print(score); // slams if (6 == val && vul) score += 750; else if (6 == val) score += 500; else if (7 == val && vul) score += 1500; else if (7 == val) score += 1000; if (Debug.debug) Debug.print(score); // overtricks int ot = tricks - val - 6; if (Debug.debug) Debug.print("ot = "+ot+", doubled = "+doubled+", ts = "+ts); if (1 == doubled) { if (Debug.debug) Debug.print("diff = "+(ts*ot)); score += ts*ot; } else { int vm = vul?2:1; if (Debug.debug) Debug.print("vm = "+vm+", diff = "+(100*(doubled-2)*vm*ot)); score += 100*(doubled/2)*vm*ot; } if (Debug.debug) Debug.print(score); // assign to the correct side if ('N' == declarer || 'S' == declarer) nsscore = score; else ewscore = score; } // contract went off else { if (Debug.debug) Debug.print("SET"); for (int i = 1; (val-i+6) >= tricks; i++) { switch (i) { case 1: score += (vul?100:50)*doubled; break; case 2: case 3: if (1 == doubled) score += (vul?100:50); else score += (vul?150:100)*doubled; break; default: if (1 == doubled) score += (vul?100:50); else score += 150*doubled; } } // assign to the correct side if ('N' == declarer || 'S' == declarer) ewscore = score; else nsscore = score; } if (Debug.debug) Debug.print("score = "+score); this.contract = ""+val+den+ (1"); // print headers output.println(""); output.println(""); for (int i = 0; i < headers.length; i++) { output.print(""+headers[i]+""); } output.println(""); output.println(""); // print rows output.println(""); for (int i = 0; i < rows.length; i++) { output.println(""); for (int j = 0; j < rows[i].length; j++) { output.print(""+rows[i][j]+""); } output.println(""); } output.println(""); output.println(""); output.flush(); } public void header(String header) { output.println("

"+header+"

"); } public void gap() { output.println("
"); } public void init() { output.println(""); output.println(""); output.println(""+title+""); output.println(""); output.println(""); } public void close() { output.println(""); output.println(""); } } salliere-0.10/cx/ath/matthew/salliere/Pair.java0000644000175000017500000001141411327142574020106 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import cx.ath.matthew.debug.Debug; import java.util.Arrays; import java.util.List; import java.util.Vector; import java.text.DecimalFormat; import java.text.FieldPosition; public class Pair { static int maxnames = 0; String number = ""; String[] names = new String[] { "", "" }; double mps; double percentage; double lps; Vector hands = new Vector(); public static synchronized int getMaxNames() { return maxnames; } public static synchronized void resetNames() { maxnames = 0; } public Pair() {} public Pair(String[] data) { int names = 0; for (int i = 1; i <= data.length; i++) if (i == data.length || (data[i].length() > 0 && (data[i].charAt(0) == '-' || data[i].charAt(0) == '.' || (data[i].charAt(0) >= '0' && data[i].charAt(0) <= '9')))) { names = i-1; break; } this.number = data[0]; this.names = new String[names]; System.arraycopy(data, 1, this.names, 0, this.names.length); if (Debug.debug) Debug.print(Debug.DEBUG, "Parsing "+names+" names: "+Arrays.deepToString(this.names)); if (data.length >= names+4) if (0 < data[names+3].length()) lps = Double.parseDouble(data[names+3]); if (data.length >= names+3) if (0 < data[names+2].length()) percentage = Double.parseDouble(data[names+2]); if (data.length >= names+2) if (0 < data[names+1].length()) mps = Double.parseDouble(data[names+1]); synchronized (Pair.class) { if (maxnames < names) maxnames = names; } } public void total(List boards) { double top = 0; int bds = 0; mps = 0; for (Board b: boards) { top = b.getTop(); if (b.played(number)) { mps += b.getMPs(number); bds++; } } percentage = (mps*100.0) / (top*bds); if (Debug.debug) Debug.print("totalling for pair "+number+": mps="+mps+", boards="+bds+", top="+top+", %age="+percentage); } public String getNumber() { return number; } public String[] getNames() { return names; } public double getMPs() { return mps; } public double getLPs() { return lps; } public double getPercentage() { return percentage; } public void setLPs(double lps) { this.lps = lps; } public void setMPs(double mps) { this.mps = mps; } public void setPercentage(double percentage) { this.percentage = percentage; } public void setNumber(String number) { this.number = number; } public void setNames(String[] names) { this.names = names; synchronized (Pair.class) { if (maxnames < names.length) maxnames = names.length; } } public String toString() { StringBuilder sb = new StringBuilder(); sb.append(number); sb.append(": "); for (String s: names) { sb.append(s); sb.append(' '); } return sb.toString(); } public String[] export() { int maxnames; synchronized (Pair.class) { maxnames = Pair.maxnames; } if (Debug.debug) Debug.print(Debug.DEBUG, "Exporting pair, "+(maxnames+4)+" fields"); String[] rv = new String[maxnames+4]; rv[0] = number; System.arraycopy(names, 0, rv, 1, names.length); for (int i = names.length+1; i <= maxnames; i++) rv[i] = ""; DecimalFormat format = new DecimalFormat("0.#"); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); StringBuffer tmp = new StringBuffer(); rv[maxnames+1] = format.format(mps, tmp, field).toString(); tmp = new StringBuffer(); rv[maxnames+3] = format.format(lps, tmp, field).toString(); format = new DecimalFormat("0.#"); tmp = new StringBuffer(); rv[maxnames+2] = format.format(percentage, tmp, field).toString(); return rv; } public void addHand(Hand h) { hands.add(h); } public List getHands() { return hands; } } salliere-0.10/cx/ath/matthew/salliere/Board.java0000644000175000017500000005274011327146372020251 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import cx.ath.matthew.debug.Debug; import static cx.ath.matthew.salliere.Gettext._; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeSet; import java.util.Set; import java.util.Vector; import java.text.MessageFormat; public class Board { public static final int NORTH = 0; public static final int SOUTH = 1; public static final int EAST = 2; public static final int WEST = 3; public static final int CLUBS = 0; public static final int DIAMONDS = 1; public static final int HEARTS = 2; public static final int SPADES = 3; public static final int NOTRUMPS = 4; class HandScoreNSComparer implements Comparator { public int compare(Hand obj1, Hand obj2) { double score1 = ( 0 == obj1.getNSScore() ) ? - obj1.getEWScore() : obj1.getNSScore(); double score2 = ( 0 == obj2.getNSScore() ) ? - obj2.getEWScore() : obj2.getNSScore(); return (int) (score1 - score2); } } class HandScoreEWComparer implements Comparator { public int compare(Hand obj1, Hand obj2) { double score1 = ( 0 == obj1.getEWScore() ) ? - obj1.getNSScore() : obj1.getEWScore(); double score2 = ( 0 == obj2.getEWScore() ) ? - obj2.getNSScore() : obj2.getEWScore(); return (int) (score1 - score2); } } Vector hands; byte[] tricks; String number = ""; Contract par; public Board() { this.hands = new Vector(); } public Board(String number) { this.number = number; this.hands = new Vector(); } public void matchPoint(int played) throws ScoreException { // order by (NS score) and (EW score) Collections.sort(hands, new HandScoreNSComparer()); Hand[] nshs = hands.toArray(new Hand[0]); Collections.sort(hands, new HandScoreEWComparer()); Hand[] ewhs = hands.toArray(new Hand[0]); // create score-frequency table Map ewfrequencies = new HashMap(); Map nsfrequencies = new HashMap(); int avcount = played-hands.size(); // scale up the board if it wasn't played as many times as others for (int i = 0; i < nshs.length; i++) { if (Debug.debug) Debug.print(nshs[i]); double score = (0 == nshs[i].getNSScore()) ? - nshs[i].getEWScore() : nshs[i].getNSScore(); if (nshs[i].isAveraged()) { if (Debug.debug) Debug.print("Average on "+nshs[i]); avcount++; } else { Double freq = nsfrequencies.get(score); if (null != freq) nsfrequencies.put(score,freq+1.0); else nsfrequencies.put(score,1.0); } } for (int i = 0; i < ewhs.length; i++) { if (Debug.debug) Debug.print(ewhs[i]); double score = (0 == ewhs[i].getEWScore()) ? - ewhs[i].getNSScore() : ewhs[i].getEWScore(); if (ewhs[i].isAveraged()) ; else { Double freq = ewfrequencies.get(score); if (null != freq) ewfrequencies.put(score,freq+1.0); else ewfrequencies.put(score,1.0); } } // increase frequencies for averages double increment = 1.0 + ( (double) avcount / (double) ( played - avcount ) ); if (Debug.debug) Debug.print("Got "+avcount+" averages, increment = "+increment); for (Double f: ewfrequencies.keySet()) ewfrequencies.put(f, ewfrequencies.get(f)*increment); for (Double f: nsfrequencies.keySet()) nsfrequencies.put(f, nsfrequencies.get(f)*increment); double avp = 0.60 * getTop(); double ave = 0.50 * getTop(); double avm = 0.40 * getTop(); for (int i = 0; i < nshs.length; i++) { double nsmps = 0.0; double score = (0 == nshs[i].getNSScore()) ? - nshs[i].getEWScore() : nshs[i].getNSScore(); if (Debug.debug) Debug.print("N/S Average: "+nshs[i].getNSAverage()); switch (nshs[i].getNSAverage()) { case Hand.AVERAGE: nsmps = ave; break; case Hand.AVERAGE_PLUS: nsmps = avp; break; case Hand.AVERAGE_MINUS: nsmps = avm; break; default: nsmps = nsfrequencies.get(score) - 1; for (Double f: nsfrequencies.keySet()) if (f < score) nsmps += ( 2 * nsfrequencies.get(f) ); } if (!nshs[i].hasForcedNSMP()) { if (nshs[i].getNSMP() == 0 || ( nshs[i].getNSMP() - nsmps <= 0.005 && nshs[i].getNSMP() - nsmps > -0.005)) nshs[i].setNSMP(nsmps); else throw new ScoreException(MessageFormat.format(_("Calculated {0} MPs for NS, but hand says: {1}"), new Object[] { nsmps, nshs[i]})); if (Debug.debug) Debug.print("Setting NSMP on board "+number+" to "+nsmps); } } for (int i = 0; i < ewhs.length; i++) { double ewmps = 0.0; double score = (0 == ewhs[i].getEWScore()) ? - ewhs[i].getNSScore() : ewhs[i].getEWScore(); if (Debug.debug) Debug.print("E/W Average: "+ewhs[i].getNSAverage()); switch (ewhs[i].getEWAverage()) { case Hand.AVERAGE: ewmps = ave; break; case Hand.AVERAGE_PLUS: ewmps = avp; break; case Hand.AVERAGE_MINUS: ewmps = avm; break; default: ewmps = ewfrequencies.get(score) - 1; for (Double f: ewfrequencies.keySet()) if (f < score) ewmps += ( 2 * ewfrequencies.get(f) ); } if (!ewhs[i].hasForcedEWMP()) { if (ewhs[i].getEWMP() == 0 || ( ewhs[i].getEWMP() - ewmps <= 0.005 && ewhs[i].getEWMP() - ewmps > -0.005)) ewhs[i].setEWMP(ewmps); else throw new ScoreException(MessageFormat.format(_("Calculated {0} MPs for EW, but hand says: {1}"), new Object[] { ewmps, ewhs[i]})); if (Debug.debug) Debug.print("Setting EWMP on board "+number+" to "+ewmps); } } } public double imp(double score) { double abs = Math.abs(score); boolean neg = score < 0; if (abs <= 10) return 0; else if (abs <= 40) return neg ? -1 : 1; else if (abs <= 80) return neg ? -2 : 2; else if (abs <= 120) return neg ? -3 : 3; else if (abs <= 160) return neg ? -4 : 4; else if (abs <= 210) return neg ? -5 : 5; else if (abs <= 260) return neg ? -6 : 6; else if (abs <= 310) return neg ? -7 : 7; else if (abs <= 360) return neg ? -8 : 8; else if (abs <= 420) return neg ? -9 : 9; else if (abs <= 490) return neg ? -10 : 10; else if (abs <= 590) return neg ? -11 : 11; else if (abs <= 740) return neg ? -12 : 12; else if (abs <= 890) return neg ? -13 : 13; else if (abs <= 1090) return neg ? -14 : 14; else if (abs <= 1290) return neg ? -15 : 15; else if (abs <= 1490) return neg ? -16 : 16; else if (abs <= 1740) return neg ? -17 : 17; else if (abs <= 1990) return neg ? -18 : 18; else if (abs <= 2240) return neg ? -19 : 19; else if (abs <= 2490) return neg ? -20 : 20; else if (abs <= 2990) return neg ? -21 : 21; else if (abs <= 3490) return neg ? -22 : 22; else if (abs <= 3990) return neg ? -23 : 23; else return neg ? -24 : 24; } public void parimp() throws ScoreException { double avs = 0; for (Hand h1: hands) { double nsimps = 0; double ewimps = 0; if (h1.isAveraged()) { // +-2 or 0 switch (h1.getNSAverage()) { case Hand.AVERAGE: nsimps = 0; break; case Hand.AVERAGE_PLUS: nsimps = 2; break; case Hand.AVERAGE_MINUS: nsimps = -2; break; } switch (h1.getEWAverage()) { case Hand.AVERAGE: ewimps = 0; break; case Hand.AVERAGE_PLUS: ewimps = 2; break; case Hand.AVERAGE_MINUS: ewimps = -2; break; } avs++; } else { // for each score, IMP against the par score double s1 = (0 == h1.getNSScore()) ? - h1.getEWScore() : h1.getNSScore(); double s2 = getParScore(); double diff = s1-s2; nsimps = imp(diff); ewimps = imp(-diff); if (Debug.debug) Debug.print(Debug.VERBOSE, "score="+s1+", par="+s2+", diff="+diff+", nsimps="+nsimps+", ewimps="+ewimps); } h1.setNSMP(nsimps); h1.setEWMP(ewimps); if (Debug.debug) Debug.print(Debug.DEBUG, h1.getNumber()+" NSMP="+nsimps+" EWMP="+ewimps); } } public double[] sumimp(String prefix, int teams) throws ScoreException { double usimps = 0; double themimps = 0; double usscore = 0; double themscore = 0; int AVNUM = 4 == teams ? 3 : 5; for (Hand h1: hands) { boolean usns = false; if (h1.getNS().startsWith(prefix)) usns = true; if (h1.isAveraged()) { // +-2 or 0 switch (usns ? h1.getNSAverage() : h1.getEWAverage()) { case Hand.AVERAGE: usimps = 0; break; case Hand.AVERAGE_PLUS: usimps = AVNUM; break; case Hand.AVERAGE_MINUS: usimps = -AVNUM; break; } switch (usns ? h1.getEWAverage() : h1.getNSAverage()) { case Hand.AVERAGE: themimps = 0; break; case Hand.AVERAGE_PLUS: themimps = AVNUM; break; case Hand.AVERAGE_MINUS: themimps = -AVNUM; break; } return new double[] { usimps, themimps }; } else { usscore += usns ? h1.getNSScore() : h1.getEWScore(); themscore += usns ? h1.getEWScore() : h1.getNSScore(); } double diff = usscore-themscore; usimps = imp(diff); themimps = imp(-diff); if (Debug.debug) Debug.print(Debug.DEBUG, h1.getNumber()+" NSMP="+usimps+" EWMP="+themimps); } return new double[] { usimps, themimps }; } public void ximp() throws ScoreException { double avs = 0; for (Hand h1: hands) { double nsimps = 0; double ewimps = 0; if (h1.isAveraged()) { // +-2 or 0 switch (h1.getNSAverage()) { case Hand.AVERAGE: nsimps = 0; break; case Hand.AVERAGE_PLUS: nsimps = 2; break; case Hand.AVERAGE_MINUS: nsimps = -2; break; } switch (h1.getEWAverage()) { case Hand.AVERAGE: ewimps = 0; break; case Hand.AVERAGE_PLUS: ewimps = 2; break; case Hand.AVERAGE_MINUS: ewimps = -2; break; } avs++; } else { // for each score, IMP against the other scores, sum, // then divide by the number of scores. for (Hand h2: hands) { if (Debug.debug) Debug.print(Debug.DEBUG, h1+" imp "+h2); if (!h2.isAveraged()) { double s1 = (0 == h1.getNSScore()) ? - h1.getEWScore() : h1.getNSScore(); double s2 = (0 == h2.getNSScore()) ? - h2.getEWScore() : h2.getNSScore(); double diff = s1-s2; nsimps += imp(diff); ewimps += imp(-diff); if (Debug.debug) Debug.print(Debug.VERBOSE, "s1="+s1+", s2="+s2+", diff="+diff+", nsimps="+nsimps+", ewimps="+ewimps); } } double s = hands.size(); nsimps = nsimps * (s / ((s-avs) * (s - 1.0))); ewimps = ewimps * (s / ((s-avs) * (s - 1.0))); } h1.setNSMP(nsimps); h1.setEWMP(ewimps); if (Debug.debug) Debug.print(Debug.DEBUG, h1.getNumber()+" NSMP="+nsimps+" EWMP="+ewimps); } } public void importTricks(String s) { String[] ss = s.split(","); tricks = new byte[ss.length]; for (int i = 0; i < ss.length; i++) tricks[i] = Byte.parseByte(ss[i]); if (Debug.debug) { Vector v = new Vector(); for (int i = 0; i < tricks.length; i++) v.add(tricks[i]); Debug.print(Debug.INFO, "Read avaiable tricks for board "+number+": "+v); } } private Contract getScore(int v, int d, int p, int vuln) throws ContractParseException, NoContractException { if (null == tricks) return null; char decl = ' '; switch (p) { case NORTH: decl = 'n'; break; case SOUTH: decl = 's'; break; case EAST: decl = 'e'; break; case WEST: decl = 'w'; break; } String contr = ""+v; switch (d) { case CLUBS: contr += "c"; break; case DIAMONDS: contr += "d"; break; case HEARTS: contr += "h"; break; case SPADES: contr += "s"; break; case NOTRUMPS: contr += "n"; break; } int tr = tricks[(4-d)+5*p]; if (tr < 6+v) contr += 'x'; if (Debug.debug) Debug.print(Debug.VERBOSE, "getScore("+v+", "+d+", "+p+", "+vuln+") tricks = "+tr+" decl = "+decl+" contr = "+contr); return new Contract(contr, decl, vuln, tr); } @SuppressWarnings("fallthrough") private int vuln() { String[] n = number.split(":"); String[] v = n[n.length-1].split(";"); int num = 0; try { num = Integer.parseInt(v[0]); } catch (NumberFormatException NFe) { if (Debug.debug) Debug.print(NFe); } int vul = Contract.NONE; if (v.length == 1) { switch (num%16) { // ns case 4: case 7: case 10: case 13: vul |= Contract.EAST; case 2: case 5: case 12: case 15: vul |= Contract.NORTH; break; // ew case 3: case 6: case 9: case 0: vul |= Contract.EAST; break; } } else { // split options String[] opts = v[1].split(","); for (String opt: opts) { String[] keyval = opt.split("="); // manual vulnerability if (keyval[0].toLowerCase().equals("vul") && 2 == keyval.length) { if (keyval[1].toLowerCase().equals("ew")) vul = Contract.EAST; else if (keyval[1].toLowerCase().equals("ns")) vul = Contract.NORTH; else if (keyval[1].toLowerCase().equals("all")) vul = Contract.NORTH | Contract.EAST; } } } return vul; } /** * @return new int[] { value, denom, declarer, nsscore } */ private Contract findPar() throws ContractParseException, NoContractException { if (null == tricks) return null; int denom = 0; int value = 1; int savedenom = -2; int savevalue = -2; int declarer = -1; int score = 0; int savescore = -1; Contract par = new Contract("P.O.", ' ', Contract.NONE, 0); int vuln = vuln(); while (denom != savedenom || value != savevalue || score != savescore) { savevalue = value; savedenom = denom; savescore = score; for (int p = NORTH; p <= WEST; p++) PLAYER: for (int v = value; v <=7; v++) for (int d = (v == value) ? denom : CLUBS; d <= NOTRUMPS; d++) { Contract c = getScore(v, d, p, vuln); int newscore = (int) (c.getNSScore() - c.getEWScore()); if (Debug.debug) Debug.print(Debug.DEBUG, "Testing "+c.getContract()+" scores "+newscore+". Current score "+score); if (((newscore > score) && (p == NORTH || p == SOUTH)) || ((newscore < score) && (p == WEST || p == EAST))) { par = c; denom = d; value = v; declarer = p; score = newscore; break PLAYER; } } if (Debug.debug) Debug.print(Debug.VERBOSE, "denom="+denom+" savedenom="+savedenom+" value="+value+" savevalue="+savevalue); } return par; } public String getParContract() { try { if (null == par) par = findPar(); } catch (Exception e) { if (Debug.debug) Debug.print(e); } return par.getContract(); } public Contract getPar() { try { if (null == par) par = findPar(); } catch (Exception e) { if (Debug.debug) Debug.print(e); } return par; } public int getParScore() { try { if (null == par) par = findPar(); } catch (Exception e) { if (Debug.debug) Debug.print(e); } return (int) (par.getNSScore()-par.getEWScore()); } public byte[] getTricks() { return tricks; } public void setTricks(byte[] tricks) { this.tricks = tricks; } public String getNumber() { return number; } public void addHand(Hand h) throws BoardValidationException { if (Debug.debug) Debug.print("Adding hand to board: "+number+"/"+hands.size()+" "+h); if (h.getNumber().length() == 0) h.setNumber(number); else if (!h.getNumber().equals(number)) throw new BoardValidationException( MessageFormat.format( _("This Hand is number {0} but this is board {1}."), new Object[] { h.getNumber(), number })); hands.add(h); h.setBoard(this); } public List getHands() { return hands; } public double getTop() { return 2*(hands.size()-1); } public double getMPs(String number) { for (Hand h: hands) if (h.getNS().equals(number)) return h.getNSMP(); else if (h.getEW().equals(number)) return h.getEWMP(); else if (h.getEW().startsWith(number+".")) return h.getEWMP(); else if (h.getEW().endsWith("."+number)) return h.getEWMP(); else if (h.getNS().startsWith(number+".")) return h.getNSMP(); else if (h.getNS().endsWith("."+number)) return h.getNSMP(); return 0; } public boolean containsAverage() { for (Hand h: hands) if (h.isAveraged()) return true; return false; } public boolean played(String number) { for (Hand h: hands) if (h.getNS().equals(number)) return true; else if (h.getEW().equals(number)) return true; else if (h.getEW().startsWith(number+".")) return true; else if (h.getEW().endsWith("."+number)) return true; else if (h.getNS().startsWith(number+".")) return true; else if (h.getNS().endsWith("."+number)) return true; return false; } public void validate() throws BoardValidationException, HandParseException { // conditions: // no pair plays the board twice Set seen = new TreeSet(); for (Hand h: hands) { h.check(); if (seen.contains(h.getNS())) throw new BoardValidationException(MessageFormat.format(_("Board {0} has been played by pair {1} twice."), new Object[] {number, h.getNS()})); else if (seen.contains(h.getEW())) throw new BoardValidationException(MessageFormat.format(_("Board {0} has been played by pair {1} twice."), new Object[] {number, h.getEW()})); else { seen.add(h.getNS()); seen.add(h.getEW()); } } } public void setNumber(String number) { this.number = number; for (Hand h: hands) h.setNumber(number); } public String toString() { return "Board number "+number+", played "+hands.size()+" times."; } } salliere-0.10/cx/ath/matthew/salliere/Salliere.java0000644000175000017500000012452711327150623020757 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import com.csvreader.CsvReader; import com.csvreader.CsvWriter; import cx.ath.matthew.debug.Debug; import static cx.ath.matthew.salliere.Gettext._; import org.apache.commons.net.ftp.FTPClient; import java.io.BufferedReader; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.Vector; import java.text.DecimalFormat; import java.text.FieldPosition; import java.text.MessageFormat; public class Salliere { // data gathered from looking at ecats-ftp sessions public static final String ECATS_SERVER = "sims.ecats.co.uk"; public static final String ECATS_USERNAME = "simsuser"; public static final String ECATS_PASSWORD = "simsuser32"; public static final String ECATS_UPLOAD_DIR = "\\sims"; public static final String ECATS_PROGRAM_VERSION = "5.6.28"; static class HandNSComparer implements Comparator { public int compare(Hand ob1, Hand ob2) { String n1 = ob1.getNS(); String n2 = ob2.getNS(); return n1.compareTo(n2); } } static class BoardNumberComparer implements Comparator { public int compare(Board ob1, Board ob2) { String n1 = ob1.getNumber(); String n2 = ob2.getNumber(); String[] n = n1.split(":"); String[] v = n[n.length-1].split(";"); int num1 = Integer.parseInt(v[0]); n = n2.split(":"); v = n[n.length-1].split(";"); int num2 = Integer.parseInt(v[0]); return num1-num2; } } static class PairNumberComparer implements Comparator { public int compare(Pair ob1, Pair ob2) { return ob1.getNumber().compareTo(ob2.getNumber()); } } static class PairPercentageComparer implements Comparator { public int compare(Pair ob1, Pair ob2) { if (Debug.debug) Debug.print(Debug.VERBOSE, "Comparing "+ob1.getNumber()+"["+ob1.getPercentage()+"] and "+ob2.getNumber()+"["+ob2.getPercentage()+"]"); // no need to split tie if (ob2.getPercentage() != ob1.getPercentage()) return (int) ((ob2.getPercentage()-ob1.getPercentage())*10000.0); List hands1 = ob1.getHands(); List hands2 = ob2.getHands(); if (hands1.size() == 0 || hands2.size() == 0) { if (Debug.debug) Debug.print(Debug.INFO, "Can't Split tie for "+ob1.getNumber()+" and "+ob2.getNumber()+", because there are no hands"); return 0; } if (Debug.debug) Debug.print(Debug.INFO, "Splitting tie for "+ob1.getNumber()+" and "+ob2.getNumber()); /* Only using this method here, so only works for all-play-all events without direct matches and only for two-way ties. Matchpoint the matchpoints for these two pairs */ if (Debug.debug) Debug.print(Debug.DEBUG, "Point-a-board count-back:"); int points1 = 0, points2 = 0; HashMap hands2map = new HashMap(); for (Hand h: hands2) hands2map.put(h.getNumber(), h); for (Hand h: hands1) { if (Debug.debug) Debug.print(Debug.VERBOSE, "Board: "+h.getNumber()); double mp1 = 0.0, mp2 = 0.0; if (h.getNS().equals(ob1.getNumber()) || h.getNS().startsWith(ob1.getNumber()+".") || h.getNS().endsWith("."+ob1.getNumber())) mp1 = h.getNSMP(); else mp1 = h.getEWMP(); if (hands2map.containsKey(h.getNumber())) { h = hands2map.remove(h.getNumber()); if (h.getNS().equals(ob2.getNumber()) || h.getNS().startsWith(ob2.getNumber()+".") || h.getNS().endsWith("."+ob2.getNumber())) mp2 = h.getNSMP(); else mp2 = h.getEWMP(); } else { if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" not played, treating as average"); mp2 = h.getBoard().getTop() / 2; } if (mp1 > mp2) { if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" win"); points1 += 2; } else if (mp1 < mp2) { if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" win"); points2 += 2; } else { if (Debug.debug) Debug.print(Debug.VERBOSE, "Draw"); points1++; points2++; } } for (Hand h: hands2map.values()) { if (Debug.debug) Debug.print(Debug.VERBOSE, "Board: "+h.getNumber()); if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" not played, treating as average"); double mp1 = 0.0, mp2 = 0.0; mp1 = h.getBoard().getTop() / 2; if (h.getNS().equals(ob2.getNumber()) || h.getNS().startsWith(ob2.getNumber()+".") || h.getNS().endsWith("."+ob2.getNumber())) mp2 = h.getNSMP(); else mp2 = h.getEWMP(); if (mp1 > mp2) { if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" win"); points1 += 2; } else if (mp1 < mp2) { if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" win"); points2 += 2; } else { if (Debug.debug) Debug.print(Debug.VERBOSE, "Draw"); points1++; points2++; } } if (Debug.debug) Debug.print(Debug.DEBUG, ob1.getNumber()+" have "+points1+" points and "+ob2.getNumber()+" have "+points2+" points."); return points2-points1; } } static void readTrickData(List boards, InputStream trickdatafile) throws IOException { Collections.sort(boards, new BoardNumberComparer()); BufferedReader br = new BufferedReader(new InputStreamReader(trickdatafile)); for (Board b: boards) { String s; if (null != (s = br.readLine())) b.importTricks(s); } } static List readBoards(InputStream is) throws IOException, BoardValidationException { CsvReader in = new CsvReader(new InputStreamReader(is)); Map boards = new HashMap(); try { while (in.readRecord()) { String[] values = in.getValues(); if (Debug.debug) { Debug.print(in.getCurrentRecord()+": "+Arrays.asList(values)); } Board b = boards.get(values[0]); if (null == b) { b = new Board(values[0]); boards.put(values[0], b); } b.addHand(new Hand(values)); } } catch (EOFException EOFe) {} in.close(); return new ArrayList(boards.values()); } static List readPairs(InputStream is, List boards) throws IOException { CsvReader in = new CsvReader(new InputStreamReader(is)); List pairs = new Vector(); HashMap pairmap = new HashMap(); try { while (in.readRecord()) { String[] values = in.getValues(); if (Debug.debug) Debug.print(Arrays.asList(values)); Pair p = new Pair(values); pairs.add(p); pairmap.put(p.getNumber(), p); } } catch (EOFException EOFe) {} in.close(); if (null != boards) { for (Board b: boards) { for (Hand h: b.getHands()) { if (pairmap.containsKey(h.getNS())) { pairmap.get(h.getNS()).addHand(h); pairmap.get(h.getEW()).addHand(h); } else { // probably individual String[] ss = h.getNS().split("\\."); for (String s: ss) if (pairmap.containsKey(s)) pairmap.get(s).addHand(h); ss = h.getEW().split("\\."); for (String s: ss) if (pairmap.containsKey(s)) pairmap.get(s).addHand(h); } } } } return pairs; } static void writePairs(List pairs, OutputStream os) throws IOException { CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); for (Pair p: pairs) out.writeRecord(p.export()); out.close(); } static void syntax() { String version = Package.getPackage("cx.ath.matthew.salliere") .getImplementationVersion(); System.out.println("Salliere Duplicate Bridge Scorer - version "+version); System.out.println("Usage: salliere [options] [commands] -- "); System.out.println(" Commands: verify score matchpoint ximp parimp total handicap localpoint results matrix boards ecats-upload ecats-export scoreteams scorecards"); System.out.println(" Options: --help --output=[:]file --title=title --orange --setsize=N --ximp --with-par --trickdata= --handicapdata= --with-handicaps --handicap-normalizer= --ecats-options= --print-ecats-options --ecats-export-dir= --mpscale= --print-mpscales --teamsize=N --teamprefix= --original-entry=<#tables>"); System.out.println(" Formats: txt html htmlfrag pdf csv"); } static void writeBoards(List boards, OutputStream os) throws IOException { CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); for (Board b: boards) for (Hand h: b.getHands()) out.writeRecord(h.export()); out.close(); } private static void doC(PrintStream out, List boards, Map options) { // write C.txt out.print("\t"); out.print("1"); //spare = 1 out.print("\t"); out.print("\"false\""); // true iff 2 winner movement out.print("\t"); out.print(""+boards.size()); // # boards played (not important) out.print("\t"); out.print("0"); // #boards/round (not important) out.print("\t"); out.print("\"true\""); // true iff contracts were recorded out.print("\t"); out.print('"'+options.get("clubName")+'"'); //club name, compulsory (max 50 chars) out.print("\t"); out.print('"'+options.get("town")+'"'); //town (max 50 chars) out.print("\t"); out.print('"'+options.get("county")+'"'); //county (max 50 chars) out.print("\t"); out.print('"'+options.get("country")+'"'); //country, compulsory, spelling agreed in advance (max 50 chars) out.print("\t"); out.print('"'+options.get("name")+'"'); //name (max 50 chars) out.print("\t"); out.print('"'+options.get("phone")+'"'); //phone, compulsory (max 50 chars) out.print("\t"); out.print('"'+options.get("fax")+'"'); //fax (max 50 chars) out.print("\t"); out.print('"'+options.get("email")+'"'); //email (max 50 chars) out.print("\t"); out.print("\"false\""); //spare = false out.print("\t"); out.print(options.get("session")); //session #, compulsory, numeric out.print("\t"); out.print('"'+ECATS_PROGRAM_VERSION+'"'); // program version. Important. My program? their program? this number seems to work... out.print("\t"); out.print('"'+options.get("date")+'"'); // "dd/mm/yyyy" out.print("\t"); out.print('"'+options.get("event")+'"'); // event name, text (max 50 chars) out.print("\r\n"); } private static void doP(PrintStream out, List pairs) { for (Pair p: pairs) { out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print(p.getNumber()); // pair number (int) out.print("\t"); String[] names = p.getNames(); if (names.length > 1) out.print('"'+names[0]+" & "+names[1]+'"'); else out.print('"'+names[0]+'"'); out.print("\t"); out.print('"'+names[0]+'"'); out.print("\t"); if (names.length > 1) out.print('"'+names[1]+'"'); else out.print('"'+'"'); out.print("\t"); out.print("\"NS\""); // for a 2 winner movement, set this to the direction they were sitting. out.print("\r\n"); } } private static void doR(PrintStream out, List boards, String session) { for (Board bd: boards) { for (Hand b: bd.getHands()) { out.print("\t"); out.print("0"); // spare == 0 out.print("\t"); out.print("\"\""); // spare == "" out.print("\t"); out.print("\"\""); // section, not used == "" out.print("\t"); out.print(b.getNumber()); // int, non zero out.print("\t"); out.print(b.getNS()); out.print("\t"); out.print(b.getEW()); out.print("\t"); out.print(""+(int) b.getNSScore()); out.print("\t"); out.print(""+(int) b.getEWScore()); out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print('"'+b.getContract()+'"'); // text, not used out.print("\t"); out.print("\""+b.getTricks()+'"'); // text, not used out.print("\t"); out.print("\""+b.getDeclarer()+'"'); // text, not used out.print("\t"); out.print(""+b.getNSMP()); // double, recalculated out.print("\t"); out.print(""+b.getEWMP()); // double, recalculated out.print("\t"); out.print('"'); if (b.isAveraged()) { out.print("A"); switch (b.getNSAverage()) { case Hand.AVERAGE_PLUS: out.print("60"); break; case Hand.AVERAGE_MINUS: out.print("40"); break; default: out.print("50"); } switch (b.getEWAverage()) { case Hand.AVERAGE_PLUS: out.print("60"); break; case Hand.AVERAGE_MINUS: out.print("40"); break; default: out.print("50"); } } out.print('"'); out.print("\t"); out.print(session); // session number again out.print("\t"); out.print("0"); //spare = 0 out.print("\t"); out.print("0"); //spare = 0 out.print("\r\n"); } } } public static void exportToECATS(List boards, List pairs, Map options, String exportdir) throws ScoreException { try { if (null == exportdir) exportdir = new File (".").getCanonicalPath(); System.err.println(_("Exporting scores in ECATS format to ")+exportdir); String session = options.get("session"); // write club file PrintStream out = new PrintStream(new FileOutputStream(exportdir+"/C.txt")); doC(out, boards, options); out.close(); // write pairs file out = new PrintStream(new FileOutputStream(exportdir+"/P.txt")); doP(out, pairs); out.close(); // write boards file out = new PrintStream(new FileOutputStream(exportdir+"/R.txt")); doR(out, boards, session); out.close(); // write end file out = new PrintStream(new FileOutputStream(exportdir+"/E.txt")); out.print("End\r\n"); out.close(); } catch (IOException IOe) { if (Debug.debug) Debug.print(IOe); throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); } System.err.println(_("ECATS files have been written. Email the files C.txt, P.txt, R.txt and E.txt to results@simpairs.com")); } public static void uploadToECATS(List boards, List pairs, Map options) throws ScoreException { System.err.println(_("Uploading scores to ECATS")); // connect FTPClient ftp = new FTPClient(); try { ftp.connect(ECATS_SERVER); ftp.login(ECATS_USERNAME, ECATS_PASSWORD); ftp.changeWorkingDirectory(ECATS_UPLOAD_DIR); ftp.setFileType(FTPClient.BINARY_FILE_TYPE); ftp.enterLocalPassiveMode(); // get options String session = options.get("session"); String clubName = options.get("clubName"); String phone = options.get("phone"); // calculate file prefix StringBuffer prefixb = new StringBuffer(); for (int i = session.length(); i < 6; i++) prefixb.append('0'); prefixb.append(session); prefixb.append(clubName.replaceAll(" ", "")); prefixb.append(phone.replaceAll(" ", "")); String prefix = prefixb.toString(); // write club file PrintStream out = new PrintStream(ftp.storeFileStream(prefix+"C.txt")); doC(out, boards, options); out.close(); if (!ftp.completePendingCommand()) throw new IOException(_("Uploading club details failed")); // write pairs file System.err.print(_("Uploading pair details")); out = new PrintStream(ftp.storeFileStream(prefix+"P.txt")); doP(out, pairs); out.close(); if (!ftp.completePendingCommand()) throw new IOException(_("Uploading pairs failed")); System.err.println(); // write boards file System.err.print(_("Uploading results")); out = new PrintStream(ftp.storeFileStream(prefix+"R.txt")); doR(out, boards, session); out.close(); System.err.println(); if (!ftp.completePendingCommand()) throw new IOException(_("Uploading results failed")); // write end file out = new PrintStream(ftp.storeFileStream(prefix+"E.txt")); out.print("End\r\n"); out.close(); if (!ftp.completePendingCommand()) throw new IOException(_("Uploading end file failed")); // log out System.err.println(_("Upload complete")); ftp.logout(); ftp.disconnect(); } catch (IOException IOe) { if (Debug.debug) Debug.print(IOe); try { ftp.logout(); ftp.disconnect(); } catch (IOException e) {} throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); } } public static void score(List boards) throws ScoreException, ContractParseException, HandParseException { for (Board b: boards) for (Hand h: b.getHands()) if (!h.isAveraged()) h.score(); modifiedboards = true; } public static void verify(List boardv, String setsize) throws MovementVerificationException, BoardValidationException, HandParseException { for (Board b: boardv) b.validate(); if (null == setsize || setsize.length() == 0) return; int size = 0; try { size = Integer.parseInt(setsize); } catch (NumberFormatException NFe) { if (Debug.debug) Debug.print(NFe); throw new MovementVerificationException(setsize+_(" isn't a number!")); } Collections.sort(boardv, new BoardNumberComparer()); Board[] boards = boardv.toArray(new Board[0]); Set pairs = new TreeSet(); for (int i = 0; i < boards.length; i++) { if (0 == (i % size)) { // reset the pairs pairs.clear(); for (Hand h: boards[i].getHands()) pairs.add(h.getNS()+" "+h.getEW()); } else { // check the pairs for (Hand h: boards[i].getHands()) if (!pairs.contains(h.getNS()+" "+h.getEW())) throw new MovementVerificationException( MessageFormat.format(_("Board {0} was played by {1} and {2}, which I was not expecting."), new Object[] { boards[i].getNumber(), h.getNS(), h.getEW() })); } } } public static void matchpoint(List boards) throws ScoreException { int played = 0; for (Board b: boards) { if (b.getHands().size() > played) played = b.getHands().size(); } for (Board b: boards) b.matchPoint(played); modifiedboards = true; } public static void ximp(List boards) throws ScoreException { for (Board b: boards) b.ximp(); modifiedboards = true; } public static void teams(List boards, TablePrinter tabular, String prefix, String teamsize) throws ScoreException { int teams = 4; if (null != teamsize && teamsize.length() >= 0) try { teams = Integer.parseInt(teamsize); } catch (NumberFormatException NFe) { if (Debug.debug) Debug.print(NFe); throw new ScoreException(teamsize+_(" isn't a number!")); } double usimps = 0; double themimps = 0; for (Board b: boards) { double[] res = b.sumimp(prefix, teams); if (res[0] > 0) usimps += res[0]; else themimps += -res[0]; } String[] headers = new String[3]; headers[0] = _("Us IMPs"); headers[1] = _("Them IMPs"); headers[2] = _("Difference"); DecimalFormat format = new DecimalFormat("0.##"); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); StringBuffer tmp; String[][] matrix = new String[1][3]; tmp = new StringBuffer(); matrix[0][0] = format.format(usimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][1] = format.format(themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][2] = format.format(usimps-themimps, tmp, field).toString(); tabular.print(headers, matrix); tabular.gap(); } public static void parimp(List boards) throws ScoreException { for (Board b: boards) b.parimp(); modifiedboards = true; } public static void total(List pairs, List boards) { for (Pair p: pairs) p.total(boards); modifiedpairs = true; } public static void matrix(List pairv, List boardv, TablePrinter tabular, String setsize) throws MovementVerificationException { int grouping = 0; if (null != setsize && setsize.length() >= 0) try { grouping = Integer.parseInt(setsize); } catch (NumberFormatException NFe) { if (Debug.debug) Debug.print(NFe); throw new MovementVerificationException(setsize+_(" isn't a number!")); } Collections.sort(boardv, new BoardNumberComparer()); Collections.sort(pairv, new PairNumberComparer()); Board[] boards = boardv.toArray(new Board[0]); Pair[] pairs = pairv.toArray(new Pair[0]); DecimalFormat format = new DecimalFormat("0.##"); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); String[] headers = new String[pairs.length+1]; headers[0] = _("Board"); for (int j = 0; j < pairs.length; j++) headers[j+1] = pairs[j].getNumber()+" "; if (0 == grouping) grouping = boards.length; String[][] matrix = new String[grouping+2][pairs.length+1]; int start = 0; while (start < boards.length) { float[] sums = new float[pairs.length]; for (int i = 0; i+start < boards.length && i < grouping; i++) { matrix[i][0] = boards[i+start].getNumber(); for (int j = 0; j < pairs.length; j++) { StringBuffer tmp = new StringBuffer(); if (boards[i+start].played(pairs[j].getNumber())) { matrix[i][j+1] = format.format(boards[i+start].getMPs(pairs[j].getNumber()), tmp, field).toString(); sums[j] += boards[i+start].getMPs(pairs[j].getNumber()); } else matrix[i][j+1] = " "; } } matrix[matrix.length-2][0] = " "; matrix[matrix.length-1][0] = _("Total"); for (int j = 0; j < sums.length; j++) { StringBuffer tmp = new StringBuffer(); matrix[matrix.length-2][j+1] = " "; matrix[matrix.length-1][j+1] = format.format(sums[j], tmp, field).toString(); } start += grouping; tabular.print(headers, matrix); tabular.gap(); } } public static void boardbyboard(List boards, TablePrinter tabular, boolean ximp, boolean withpar) { String[] headers = new String[] { _("NS"), _("EW"), _("Contract"), _("By"), _("Tricks"), _("Score:"), "", ximp ? _("IMPs") : _("MPs:"), "" }; Collections.sort(boards, new BoardNumberComparer()); for (Board b: boards) { Vector lines = new Vector(); List hands = b.getHands(); Collections.sort(hands, new HandNSComparer()); for (Hand h: hands) { String[] ex = h.export(); String[] line = new String[ex.length-1]; System.arraycopy(ex, 1, line, 0, line.length); lines.add(line); } if (withpar) tabular.header(_("Board: ")+b.getNumber()+" [ "+b.getParContract()+" by "+b.getPar().getDeclarer()+" ]"); else tabular.header(_("Board: ")+b.getNumber()); tabular.print(headers, lines.toArray(new String[0][])); tabular.gap(); } } public static void scorecards(List pairs, List boards, TablePrinter tabular, boolean ximp) { String[] headers; if (0 == pairs.size()) return; if (pairs.get(0).getNames().length > 1) { headers = new String[] { _("Board"), _("Dir"), _("VS"), _("Contract"), _("By"), _("Tricks"), _("Score:"), "", ximp ? _("IMPs") : _("MPs:")}; if (Debug.debug) Debug.print("Pairs"); } else { headers = new String[] { _("Board"), _("Dir"), _("Contract"), _("By"), _("Tricks"), _("Score:"), "", ximp ? _("IMPs") : _("MPs:")}; if (Debug.debug) Debug.print("Individual"); } Collections.sort(pairs, new PairNumberComparer()); Collections.sort(boards, new BoardNumberComparer()); for (Pair p: pairs) { String header; if (p.getNames().length == 1) header = _("Player "); else header = _("Pair "); header += p.getNumber(); for (String n: p.getNames()) { header += ", "+n; } tabular.header(header); Vector lines = new Vector(); for (Board b: boards) { List hands = b.getHands(); Collections.sort(hands, new HandNSComparer()); for (Hand h: hands) { if (h.getNS().equals(p.getNumber())) { String[] ex = h.export(); String[] line = new String[ex.length-1]; line[0] = ex[0]; line[1] = _("NS"); line[2] = ex[2]; line[3] = ex[3]; line[4] = ex[4]; line[5] = ex[5]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[7] = ex[7].equals("0") ? "" : ex[7]; line[8] = ex[8]; lines.add(line); } else if (h.getEW().equals(p.getNumber())) { String[] ex = h.export(); String[] line = new String[ex.length-1]; line[0] = ex[0]; line[1] = _("EW"); line[2] = ex[1]; line[3] = ex[3]; line[4] = ex[4]; line[5] = ex[5]; line[6] = ex[7].equals("0") ? "" : ex[7]; line[7] = ex[6].equals("0") ? "" : ex[6]; line[8] = ex[9]; lines.add(line); } else if (h.getNS().startsWith(p.getNumber()+".")) { String[] ex = h.export(); String[] line = new String[ex.length-2]; line[0] = ex[0]; line[1] = _("N"); line[2] = ex[3]; line[3] = ex[4]; line[4] = ex[5]; line[5] = ex[7].equals("0") ? "" : ex[7]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[7] = ex[9]; lines.add(line); } else if (h.getNS().endsWith("."+p.getNumber())) { String[] ex = h.export(); String[] line = new String[ex.length-2]; line[0] = ex[0]; line[1] = _("S"); line[2] = ex[3]; line[3] = ex[4]; line[4] = ex[5]; line[5] = ex[7].equals("0") ? "" : ex[7]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[7] = ex[9]; lines.add(line); } else if (h.getEW().startsWith(p.getNumber()+".")) { String[] ex = h.export(); String[] line = new String[ex.length-2]; line[0] = ex[0]; line[1] = _("E"); line[2] = ex[3]; line[3] = ex[4]; line[4] = ex[5]; line[5] = ex[7].equals("0") ? "" : ex[7]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[7] = ex[9]; lines.add(line); } else if (h.getEW().endsWith("."+p.getNumber())) { String[] ex = h.export(); String[] line = new String[ex.length-2]; line[0] = ex[0]; line[1] = _("W"); line[2] = ex[3]; line[3] = ex[4]; line[4] = ex[5]; line[5] = ex[7].equals("0") ? "" : ex[7]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[7] = ex[9]; lines.add(line); } } } tabular.print(headers, lines.toArray(new String[0][])); tabular.gap(); } } public static Map readHandicapData(List pairs, InputStream handicapfile) throws ScoreException { Map handicaps = new HashMap(); Map pairhandicaps = new HashMap(); try { CsvReader in = new CsvReader(new InputStreamReader(handicapfile)); while (in.readRecord()) { String[] values = in.getValues(); if (values.length != 2) throw new ScoreException(_("Malformed handicap line: ")+Arrays.deepToString(values)); handicaps.put(values[0], new Double(values[1])); } in.close(); } catch (IOException IOe) { if (Debug.debug) Debug.print(IOe); throw new ScoreException(_("Failure in reading handicap file: ")+IOe.getMessage()); } for (Pair p: pairs) { double handicap = 0.0; String[] names = p.getNames(); for (String n: names) { Double v = handicaps.get(n); if (null == v) v = 50.0; handicap += v; } handicap /= (double) names.length; pairhandicaps.put(p, handicap); } return pairhandicaps; } public static void handicap(List pairs, Map handicaps, double normalize) throws ScoreException { if (null == handicaps) throw new ScoreException(_("Must supply a handicap file before calculating handicapped scores")); for (Pair p: pairs) { double handicap = handicaps.get(p); p.setPercentage(p.getPercentage()-handicap+normalize); } modifiedpairs = true; } public static void localpoint(List pairs, List boards, MasterPointScale scale, int originaltables) throws ScoreException { // sort pairs in order Collections.sort(pairs, new PairPercentageComparer()); Pair[] ps = pairs.toArray(new Pair[0]); if (ps.length == 0) return; int npairs; int arity = ps[0].getNames().length; if (-1 == originaltables) npairs = ps.length; else npairs = originaltables * arity; // check we have enough to give LPs if (ps.length < scale.minPairs(arity)) throw new ScoreException( MessageFormat.format(_("Must have at least {0} competitors to award local points in this event"), new Object[] { new Integer(scale.minPairs(arity)) })); // calculate LP scale based on number of pairs int[] LPs = new int[ps.length]; int awarded = scale.numberAwards(npairs, arity, boards.size()); double top = scale.getTop(npairs, arity, boards.size()); double rate = scale.getRate(arity); if (Debug.debug) Debug.print(Debug.DEBUG, "Awarding LPs to "+ps.length+" pairs, top is "+top+" rate is "+rate+" number receiving LPs: "+awarded); double lp = top; for (int i = 0; i < LPs.length && i < awarded; i++, lp -= rate) if (lp > scale.getMax(boards.size())) LPs[i] = scale.getMax(boards.size()); else LPs[i] = (int) Math.ceil(lp); // award LPs, splitting on draws for (int i = 0; i < ps.length && i < awarded; i++) { int a = i; int total = LPs[i]; while (i+1 < ps.length && ps[i].getPercentage()==ps[i+1].getPercentage()) total += LPs[++i]; double award = Math.ceil(total / (1.0+i-a)); if (award < scale.getMin() && award > 0) award = scale.getMin(); for (int j = a; j <= i; j++) { if (ps[j].getLPs() != 0 && ps[j].getLPs() != award) throw new ScoreException( MessageFormat.format(_("Calculated {0} LPs for pair {1} but data says {2}."), new Object[] { award, ps[j].getNumber(), ps[j].getLPs() })); ps[j].setLPs(award); } } modifiedpairs = true; } public static void results(List pairs, TablePrinter tabulate, boolean orange, boolean ximp, Map handicapdata, boolean handicaps) { Vector results = new Vector(); Collections.sort(pairs, new PairPercentageComparer()); Vector headerv = new Vector(); if (Pair.getMaxNames() == 1) { headerv.add(_("Num")); headerv.add(_("Name")); } else { headerv.add(_("Pair")); headerv.add(_("Names")); for (int i = 1; i < Pair.getMaxNames(); i++) headerv.add(""); } if (ximp) headerv.add(_("IMPs")); else { headerv.add(_("MPs")); if (handicaps) headerv.add(_("h'cap")); headerv.add(_("%age")); } if (orange) headerv.add(_("OPs")); else headerv.add(_("LPs")); String[] header = headerv.toArray(new String[0]); if (ximp) for (Pair p: pairs) { String[] a = p.export(); String[] b = new String[a.length-1]; System.arraycopy(a, 0, b, 0, 4); System.arraycopy(a, 5, b, 4, a.length-5); results.add(b); } else for (Pair p: pairs) results.add(p.export()); if (handicaps) for (int i = 0; i < pairs.size(); i++) { Pair p = pairs.get(i); String[] r = results.get(i); String[] n = new String[r.length+1]; System.arraycopy(r, 0, n, 0, r.length-2); DecimalFormat format = new DecimalFormat("0.#"); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); StringBuffer tmp = new StringBuffer(); n[r.length-2] = format.format(handicapdata.get(p), tmp, field).toString(); if (Debug.debug) Debug.print("Printing handicap "+n[r.length-2]+" for "+p); System.arraycopy(r, r.length-2, n, r.length-1, 2); results.set(i, n); } tabulate.print(header, results.toArray(new String[0][])); tabulate.gap(); } public static boolean modifiedpairs = false; public static boolean modifiedboards = false; public static void main(String[] args) { try { if (Debug.debug) { File f = new File("debug.conf"); if (f.exists()) Debug.loadConfig(f); Debug.setThrowableTraces(true); } Vector commands = new Vector(); HashMap options = new HashMap(); options.put("--output", "-"); options.put("--help", null); options.put("--orange", null); options.put("--ximp", null); options.put("--title", _("Salliere Duplicate Bridge Scorer: Results")); options.put("--teamsize", null); options.put("--teamprefix", ""); options.put("--setsize", null); options.put("--with-par", null); options.put("--with-handicaps", null); options.put("--trickdata", null); options.put("--handicapdata", null); options.put("--handicap-normalizer", "0.0"); options.put("--ecats-options", null); options.put("--ecats-export-dir", null); options.put("--print-ecats-options", null); options.put("--print-mpscales", null); options.put("--mpscale", null); options.put("--original-entry", "-1"); int i; for (i = 0; i < args.length; i++) { if ("--".equals(args[i])) break; else if (args[i].startsWith("--")) { String[] opt = args[i].split("="); if (Debug.debug) Debug.print(Arrays.asList(opt)); if (options.containsKey(opt[0])) { if (opt.length == 1) options.put(opt[0], "true"); else options.put(opt[0], opt[1]); } else { System.out.println(_("Error: unknown option ")+opt[0]); syntax(); System.exit(1); } } else commands.add(args[i]); } if (null != options.get("--help")) { syntax(); System.exit(1); } if (null != options.get("--print-ecats-options")) { ECatsOptionsMap.printOptions(); System.exit(1); } if (null != options.get("--print-mpscales")) { MasterPointScale.printScales(); System.exit(1); } if (args.length < (i+3)) { System.out.println(_("You must specify boards.csv and names.csv")); syntax(); System.exit(1); } List boards; List pairs; boards = readBoards(new FileInputStream(args[i+1])); pairs = readPairs(new FileInputStream(args[i+2]), boards); if (null != options.get("--trickdata")) { readTrickData(boards, new FileInputStream(options.get("--trickdata"))); } Map handicapdata = null; if (null != options.get("--handicapdata")) { handicapdata = readHandicapData(pairs, new FileInputStream(options.get("--handicapdata"))); } Map ecatsoptions = new ECatsOptionsMap(options.get("--ecats-options")); TablePrinter tabular = null; String[] format = options.get("--output").split(":"); PrintStream out; if ("-".equals(format[format.length-1])) out = System.out; else out = new PrintStream(new FileOutputStream(format[format.length-1])); if (format.length == 1) tabular = new AsciiTablePrinter(out); else if ("txt".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); else if ("csv".equals(format[0].toLowerCase())) tabular = new CSVTablePrinter(out); else if ("html".equals(format[0].toLowerCase())) tabular = new HTMLTablePrinter(options.get("--title"), out); else if ("htmlfrag".equals(format[0].toLowerCase())) tabular = new HTMLFragTablePrinter(options.get("--title"), out); else if ("pdf".equals(format[0].toLowerCase())) tabular = new PDFTablePrinter(options.get("--title"), out); else { System.out.println(_("Unknown format: ")+format[0]); syntax(); System.exit(1); } tabular.init(); tabular.header(options.get("--title")); for (String command: commands) { if ("score".equals(command)) score(boards); else if ("verify".equals(command)) verify(boards, options.get("--setsize")); else if ("matchpoint".equals(command)) matchpoint(boards); else if ("total".equals(command)) total(pairs, boards); else if ("results".equals(command)) results(pairs, tabular, null != options.get("--orange"), null != options.get("--ximp"), handicapdata, null != options.get("--with-handicaps")); else if ("matrix".equals(command)) matrix(pairs, boards, tabular, options.get("--setsize")); else if ("boards".equals(command)) boardbyboard(boards, tabular, null != options.get("--ximp"), null != options.get("--with-par")); else if ("scorecards".equals(command)) scorecards(pairs, boards, tabular, null != options.get("--ximp")); else if ("localpoint".equals(command)) localpoint(pairs, boards, MasterPointScale.getScale(options.get("--mpscale")), Integer.parseInt(options.get("--original-entry"))); else if ("handicap".equals(command)) handicap(pairs, handicapdata, Double.parseDouble(options.get("--handicap-normalizer"))); else if ("ximp".equals(command)) ximp(boards); else if ("parimp".equals(command)) parimp(boards); else if ("ecats-upload".equals(command)) uploadToECATS(boards, pairs, ecatsoptions); else if ("ecats-export".equals(command)) exportToECATS(boards, pairs, ecatsoptions, options.get("--ecats-export-dir")); else if ("scoreteams".equals(command)) teams(boards, tabular, options.get("--teamprefix"), options.get("--teamsize")); else { System.out.println(_("Bad Command: ")+command); syntax(); System.exit(1); } } tabular.close(); out.close(); if (modifiedboards) writeBoards(boards, new FileOutputStream(args[i+1])); if (modifiedpairs) writePairs(pairs, new FileOutputStream(args[i+2])); } catch (Exception e) { if (Debug.debug) { Debug.setThrowableTraces(true); Debug.print(Debug.ERR, e); } System.out.println(_("Salliere failed to compute results: ")+e.getMessage()); System.exit(1); } } } salliere-0.10/cx/ath/matthew/salliere/TablePrinter.java0000644000175000017500000000177511134734605021615 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; public interface TablePrinter { public void print(String[] headers, String[][] rows); public void header(String header); public void gap(); public void init(); public void close(); } salliere-0.10/cx/ath/matthew/salliere/CSVTablePrinter.java0000644000175000017500000000317511155037114022157 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import cx.ath.matthew.debug.Debug; import java.io.PrintStream; import java.util.Arrays; public class CSVTablePrinter implements TablePrinter { private PrintStream output; public CSVTablePrinter(PrintStream output) { this.output = output; } public void print(String[] headers, String[][] rows) { for (int i = 0; i < headers.length; i++) { output.print(headers[i]); output.print(','); } output.println(); for (int i = 0; i < rows.length; i++) { for (int j = 0; j < rows[i].length; j++) { output.print(rows[i][j]); output.print(','); } output.println(); } output.flush(); } public void header(String header) { } public void gap() { } public void init() {} public void close() {} } salliere-0.10/cx/ath/matthew/salliere/.Salliere.java.swp0000644000175000017500000016000011212763416021632 0ustar mjj29mjj29b0VIM 7.1ç+Jïg"smjj29qadesh~mjj29/scm/salliere/cx/ath/matthew/salliere/Salliere.javautf-8 3210#"! Utp ÿ3 4Ts 4Œ aë _L \«YQDmDmDmad¨ˆ 3üØÔ®«`Ây,à • H ( % ó ð ì ë Ê É © ‰ ˆ e 4 3  ÷ â  ¡ … c G *  ë Ï ¶ ˜ { a J 4   ë Í ® ˆ ‡ Z \ F D Ì‘TÙØ£žme:íåàߥ og7ⲆjCûóîí´¯~v( ÝØ§ŸD<76ÞÙžIH ÷ö String s; for (Board b: (Board[]) boards.toArray(new Board[0])) { BufferedReader br = new BufferedReader(new InputStreamReader(trickdatafile)); Collections.sort(boards, new BoardNumberComparer()); { static void readTrickData(List boards, InputStream trickdatafile) throws IOException } } return (int) ((((Pair) ob2).getPercentage()-((Pair) ob1).getPercentage())*100.0); { public int compare(Object ob1, Object ob2) { static class PairPercentageComparer implements Comparator } } return ((Pair) ob1).getNumber().compareTo(((Pair) ob2).getNumber()); { public int compare(Object ob1, Object ob2) { static class PairNumberComparer implements Comparator } } return num1-num2; int num2 = Integer.parseInt(v[0]); v = n[n.length-1].split(";"); n = n2.split(":"); int num1 = Integer.parseInt(v[0]); String[] v = n[n.length-1].split(";"); String[] n = n1.split(":"); String n2 = ((Board) ob2).getNumber(); String n1 = ((Board) ob1).getNumber(); { public int compare(Object ob1, Object ob2) { static class BoardNumberComparer implements Comparator } } return n1.compareTo(n2); String n2 = ((Hand) ob2).getNS(); String n1 = ((Hand) ob1).getNS(); { public int compare(Object ob1, Object ob2) { static class HandNSComparer implements Comparator public static final String ECATS_PROGRAM_VERSION = "5.6.28"; public static final String ECATS_UPLOAD_DIR = "\\sims"; public static final String ECATS_PASSWORD = "simsuser32"; public static final String ECATS_USERNAME = "simsuser"; public static final String ECATS_SERVER = "sims.ecats.co.uk"; // data gathered from looking at ecats-ftp sessions{public class Sallierimport java.util.zip.ZipOutputStream;import iimport java.util.zip.ZipOutputStream;import java.util.zip.ZipEntry;import java.util.zip.ZipFile;import java.util.Vector;import java.util.TreeSet;import java.util.Set;import java.util.Map;import java.util.List;import java.util.HashMap;import java.util.Comparator;import java.util.Collections;import java.util.Arrays;import java.util.ArrayList;import java.io.PrintStream;import java.io.OutputStreamWriter;import java.io.OutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.InputStream;import java.io.FileOutputStream;import java.io.FileInputStream;import java.io.File;import java.io.EOFException;import java.io.BufferedReader;import static cx.ath.matthew.salliere.Gettext._;import cx.ath.matthew.debug.Debug;import com.csvreader.CsvWriter;import com.csvreader.CsvReader;package cx.ath.matthew.salliere; */ * * To Contact me, please email src@matthew.ath.cx * * Boston, MA 02111-1307, USA. * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * copy of the GNU General Public License along with this program; if not, * GNU General Public License for more details. You should have received a * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * the Free Software Foundation. This program is distributed in the hope that * under the terms of the GNU General Public License Version 2 as published by * This program is free software; you can redistribute it and/or modify it * * Copyright (C) 2007 Matthew Johnson * * Salliere Duplicate Bridge Scorer/* ad/SDÆt6à§VFï Ó È ¾ ¥ k j  æ „ = ù 9 Ç 7 ñ ^ # äƒöaNö×ɾ½£‡yNýÊ«”bE. ðµd_A%ùÝÒ{bZUS2 ß»}}} } } System.exit(} } } System.exit(1); } } } System.exit(1); } } } System.ex} } } System.exit(1); System.out.println(_("Salliere failed to compute results: ")+e.getMessage()); } Debug.print(e); Debug.setThrowableTraces(true); if (Debug.debug) { } catch (Exception e) { } writePairs(pairs, new FileOutputStream(args[i+2])); if (modifiedpairs) writeBoards(boards, new FileOutputStream(args[i+1])); if (modifiedboards) } else { } zos.close(); zos.closeEntry(); writePairs(pairs, zos); zos.putNextEntry(new ZipEntry("names.csv")); zos.closeEntry(); writeBoards(boards, zos); zos.putNextEntry(new ZipEntry("boards.csv")); ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(args[i+1])); if (modifiedboards || modifiedpairs) { if (zip) { out.close(); tabular.close(); } } System.exit(1); syntax(); System.out.println(_("Bad Command: ")+command); else { else if ("scoreteams".equals(command)) teams(boards, tabular, (String) options.get("--teamprefix"), (String) options.get("--teamsize")); else if ("ecats-export".equals(command)) exportToECATS(boards, pairs, ecatsoptions, (String) options.get("--ecats-export-dir")); else if ("ecats-upload".equals(command)) uploadToECATS(boards, pairs, ecatsoptions); else if ("parimp".equals(command)) parimp(boards); else if ("ximp".equals(command)) ximp(boards); else if ("handicap".equals(command)) handicap(pairs, handicapdata, Double.parseDouble((String) options.get("--handicap-normalizer"))); else if ("localpoint".equals(command)) localpoint(pairs); else if ("boards".equals(command)) boardbyboard(boards, tabular, null != options.get("--ximp"), null != options.get("--with-par")); else if ("matrix".equals(command)) matrix(pairs, boards, tabular, (String) options.get("--setsize")); else if ("results".equals(command)) results(pairs, tabular, null != options.get("--orange"), null != options.get("--ximp"), handicapdata, null != options.get("--with-handicaps")); else if ("total".equals(command)) total(pairs, boards); else if ("matchpoint".equals(command)) matchpoint(boards); else if ("verify".equals(command)) verify(boards, (String) options.get("--setsize")); if ("score".equals(command)) score(boards); for (String command: (String[]) commands.toArray(new String[0])) { tabular.header((String) options.get("--title")); tabular.init(); } System.exit(1); syntax(); System.out.println(_("Unknown format: ")+format[0]); else { tabular = new PDFTablePrinter((String) options.get("--title"), out); else if ("pdf".equals(format[0].toLowerCase())) tabular = new HTMLFragTablePrinter((String) options.get("--title"), out); else if ("htmlfrag".equals(format[0].toLowerCase())) tabular = new HTMLTablePrinter((String) options.get("--title"), out); else if ("html".equals(format[0].toLowerCase()))adåTÖ·¯®©¨QL ëÞ»n Ý À — n ` 7 ,  õ È Ã Â † B !  ñ à ‚ Y N )   þ ý ³ ® h / ú õ ô Ü × ’ W  ‡ñÄQ ¾s.÷»‚N᫦¥¤XS ÐdUPå8ÿê執® ou out.print("\t"); out.print("1"); //spare = 1 out.pri public static void score(List boards) throws ScoreException, ContractParseException, HandParseException } out.flush(); out.writeRecord(h.export()); for (Hand h: (Hand[]) b.getHands().toArray(new Hand[0])) for (Board b: (Board[]) boards.toArray(new Board[0])) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writeBoards(List boards, OutputStream os) throws IOException } System.out.println(" event = event name"); System.out.println(" date = event date"); System.out.println(" county = club county"); System.out.println(" town = club town"); System.out.println(" email = contact email"); System.out.println(" fax = contact fax number"); System.out.println(" name = contact name"); System.out.println(" country = club country (required)"); System.out.println(" phone = contact phone number (required)"); System.out.println(" session = ECATS session number (required)"); System.out.println(" clubName = name of club (required)"); System.out.println(" ECATS options: "); System.out.println(" Formats: txt html htmlfrag pdf csv"); System.out.println(" Options: --help --output=[:]file --title=title --orange --setsize=N --ximp --with-par --trickdata= --handicapdata= --with-handicaps --handicap-normalizer= --ecats-options= --teamsize=N --teamprefix="); System.out.println(" Commands: verify score matchpoint ximp parimp total handicap localpoint results matrix boards ecats-upload scoreteams"); System.out.println("Usage: salliere [options] [commands] -- [ [descriptor.csv]|]"); System.out.println("Salliere Duplicate Bridge Scorer - version "+version); .getImplementationVersion(); String version = Package.getPackage("cx.ath.matthew.salliere") { static void syntax() } out.flush(); out.writeRecord(p.export()); for (Pair p: (Pair[]) pairs.toArray(new Pair[0])) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writePairs(List pairs, OutputStream os) throws IOException } return pairs; in.close(); } catch (EOFException EOFe) {} } pairs.add(new Pair(values)); if (Debug.debug) Debug.print(Arrays.asList(values)); String[] values = in.getValues(); while (in.readRecord()) { try { List pairs = new Vector(); CsvReader in = new CsvReader(new InputStreamReader(is)); { static List readPairs(InputStream is) throws IOException } return new ArrayList(boards.values()); in.close(); } catch (EOFException EOFe) {} } b.addHand(new Hand(values)); } boards.put(values[0], b); b = new Board(values[0]); if (null == b) { Board b = (Board) boards.get(values[0]); } Debug.print(in.getCurrentRecord()+": "+Arrays.asList(values)); if (Debug.debug) { String[] values = in.getValues(); while (in.readRecord()) { try { Map boards = new HashMap(); CsvReader in = new CsvReader(new InputStreamReader(is)); { static List readBoards(InputStream is) throws IOException, BoardValidationException } } b.importTricks(s); if (null != (s = br.readLine()))adiáYÁ¢—–x<&! 𿾔ƒg:ú Î Ã š p I # û Õ „ Z 0  Ý ­ ‚ T  ï ½ ­ € S " ð ¯ } V $ ÛÃy];*ñæåÁbL0%$öàŸ¢ŒpUT-,õÀQµ„UIæáÑ«‘_A2àß¾ŒS!è¸ tabular = new CSVTablePrinter(out); else if ("csv".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); else if ("txt".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); if (format.length == 1) out = new PrintStream(new FileOutputStream(format[format.length-1])); else out = System.out; if ("-".equals(format[format.length-1])) PrintStream out; String[] fo } pairStr } pairStream = new FileInputStream(args[i+2]); boardStream = new FileInputStream(args[i+1]); } else { pairStream = zf.getInputStream(pairEntry); boardStream = zf.getInputStream(boardEntry); if (null == pairEntry) throw new Exception(_("Cannot find pairs in combined data file ")+args[i+1]); ZipEntry pairEntry = zf.getEntry("names.csv"); if (null == boardEntry) throw new Exception(_("Cannot find travellers in combined data file ")+args[i+1]); ZipEntry boardEntry = zf.getEntry("boards.csv"); ZipFile zf = new ZipFile(args[i+1]); if (zip) { boolean zip = args.length == (i+2); InputStream pairStream; InputStream boardStream; List pairs; List boards; } System.exit(1); syntax(); if (null != options.get("--help")) { } System.exit(1); syntax(); System.out.println(_("You must specify session.sal or boards.csv and names.csv")); if (args.length < (i+2)) { } commands.add(args[i]); } else } System.exit(1); syntax(); System.out.println(_("Error: unknown option ")+opt[0]); } else { options.put(opt[0], opt[1]); else options.put(opt[0], "true"); if (opt.length == 1) if (options.containsKey(opt[0])) { if (Debug.debug) Debug.print(Arrays.asList(opt)); String[] opt = args[i].split("="); else if (args[i].startsWith("--")) { if ("--".equals(args[i])) break; for (i = 0; i < args.length; i++) { int i; options.put("--ecats-export-dir", null); options.put("--ecats-options", null); options.put("--handicap-normalizer", "0.0"); options.put("--handicapdata", null); options.put("--trickdata", null); options.put("--with-handicaps", null); options.put("--with-par", null); options.put("--setsize", null); options.put("--teamprefix", ""); options.put("--teamsize", null); options.put("--title", _("Salliere Duplicate Bridge Scorer: Results")); options.put("--ximp", null); options.put("--orange", null); options.put("--help", null); options.put("--output", "-"); HashMap options = new HashMap(); Vector commands = new Vector(); } Debug.setThrowableTraces(true); Debug.loadConfig(f); if (f.exists()) File f = new File("debug.conf"); if (Debug.debug) { try { { public static void main(String[] args) public static boolean modifiedboards = false; public static boolean modifiedpairs = false; } tabulate.gap(); (String[][]) results.toArray(new String[0][])); tabulate.print(header, } results.set(i, n); System.arraycopy(r, r.length-2, n, r.length-1, 2);adß o ÿÔ¬«xíì¶E:9ß Þ ¸ · b H  ø é — – u C Ø Ÿ o tabular = new CSVT tabular = new CSVTablePrinter(out); else if ("csv".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); else if ("txt".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); if (format.length == 1) out = new PrintStream(new FileOutputStream(format[format.length-1])); else out = System.out; if ("-".equals(format[format.length-1])) PrintStream out; String[] format = (String[]) ((String) options.get("--output")).split(":"); TablePrinter tabular = null; Map ecatsoptions = new ECatsOptionsMap((String) options.get("--ecats-options")); } handicapdata = readHandicapData(pairs, new FileInputStream((String) options.get("--handicapdata"))); if (null != options.get("--handicapdata")) { Map handicapdata = null; } readTrickData(boards, new FileInputStream((String) options.get("--trickdata"))); if (null != options.get("--trickdata")) { pairs = readPairs(pairStream); boards = readBoards(boardStream);ad}VÄ­gPÁªH1ä Í | e ê Ó † o  ý ² › L 5  ð † ÿ è   ‰ .    ×Ò˜~X>þƬ„O5õϵM1)$ÛÖ—R5 îÀ£iLøÖ¹—zJ-ýà·šX;úÝš}| out.print("\t"); out.print("\""+b.getDeclarer()+'"'); // text, not used out.print("\t"); out.print("\""+b.getTricks()+'"'); // text, not used out.print("\t"); out.print('"'+b.getContract()+'"'); // text, not used out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print(""+(int) b.getEWScore()); out.print("\t"); out.print(""+(int) b.getNSScore()); out.print("\t"); out.print(b.getEW()); out.print("\t"); out.print(b.getNS()); out.print("\t"); out.print(b.getNumber()); // int, non zero out.print("\t"); out.print("\"\""); // section, not used == "" out.print("\t"); out.print("\"\""); // spare == "" out.print("\t"); out.print("0"); // spare == 0 out.print("\t"); for (Hand b: (Hand[]) bd.getHands().toArray(new Hand[0])) { for (Board bd: (Board[]) boards.toArray(new Board[0])) { { private static void doR(PrintStream out, List boards, String session) } } out.print("\r\n"); out.print("\"NS\""); // for a 2 winner movement, set this to the direction they were sitting. out.print("\t"); out.print('"'+names[1]+'"'); out.print("\t"); out.print('"'+names[0]+'"'); out.print("\t"); out.print('"'+names[0]+" & "+names[1]+'"'); String[] names = p.getNames(); out.print("\t"); out.print(p.getNumber()); // pair number (int) out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); for (Pair p: (Pair[]) pairs.toArray(new Pair[0])) { { private static void doP(PrintStream out, List pairs) } out.print("\r\n"); out.print('"'+(String) options.get("event")+'"'); // event name, text (max 50 chars) out.print("\t"); out.print('"'+(String) options.get("date")+'"'); // "dd/mm/yyyy" out.print("\t"); out.print('"'+ECATS_PROGRAM_VERSION+'"'); // program version. Important. My program? their program? this number seems to work... out.print("\t"); out.print((String) options.get("session")); //session #, compulsory, numeric out.print("\t"); out.print("\"false\""); //spare = false out.print("\t"); out.print('"'+(String) options.get("email")+'"'); //email (max 50 chars) out.print("\t"); out.print('"'+(String) options.get("fax")+'"'); //fax (max 50 chars) out.print("\t"); out.print('"'+(String) options.get("phone")+'"'); //phone, compulsory (max 50 chars) out.print("\t"); out.print('"'+(String) options.get("name")+'"'); //name (max 50 chars) out.print("\t"); out.print('"'+(String) options.get("country")+'"'); //country, compulsory, spelling agreed in advance (max 50 chars) out.print("\t"); out.print('"'+(String) options.get("county")+'"'); //county (max 50 chars) out.print("\t"); out.print('"'+(String) options.get("town")+'"'); //town (max 50 chars) out.print("\t"); out.print('"'+(String) options.get("clubName")+'"'); //club name, compulsory (max 50 chars) out.print("\t"); out.print("\"true\""); // true iff contracts were recorded out.print("\t"); out.print("0"); // #boards/round (not important) out.print("\t"); out.print(""+boards.size()); // # boards played (not important) out.print("\t"); out.print("\"false\""); // true iff 2 winner movementad»iÁ¤eH, ëÀ–pT)ç Ì ¦ • j @  þ Ó ­ ‘ v P ? 1  ø À £ { ^ 6   ÿ þ Œ ‡ { [ Î Í ’ Ž r  øâáÄz`JI+á½§¦‹A"  é½NFEÀ»º¹YTáÕ±}FêéÑ–Y"!ÿË—vTé¼» String prefix = prefixb.toString(); prefixb.append(phone.replaceAll(" ", "")); prefixb.append(clubName.replaceAll(" ", "")); prefixb.append(session); prefixb.append('0'); for (int i = session.length(); i < 6; i++) StringBuffer prefixb = new StringBuffer(); // calculate file prefix String phone = (String) options.get("phone"); String clubName = (String) options.get("clubName"); String session = (String) options.get("session"); // get options ftp.enterLocalPassiveMode(); ftp.setFileType(FTPClient.BINARY_FILE_TYPE); ftp.changeWorkingDirectory(ECATS_UPLOAD_DIR); ftp.login(ECATS_USERNAME, ECATS_PASSWORD); ftp.connect(ECATS_SERVER); try { FTPClient ftp = new FTPClient(); // connect System.err.println(_("Uploading scores to ECATS")); { public static void uploadToECATS(List boards, List pairs, Map options) throws ScoreException } System.err.println(_("ECATS files have been written. Email the files C.txt, P.txt, R.txt and E.txt to results@simpairs.com")); } throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { out.close(); out.print("End\r\n"); out = new PrintStream(new FileOutputStream(exportdir+"/E.txt")); // write end file out.close(); doR(out, boards, session); out = new PrintStream(new FileOutputStream(exportdir+"/R.txt")); // write boards file out.close(); doP(out, pairs); out = new PrintStream(new FileOutputStream(exportdir+"/P.txt")); // write pairs file out.close(); doC(out, boards, options); PrintStream out = new PrintStream(new FileOutputStream(exportdir+"/C.txt")); // write club file String session = (String) options.get("session"); System.err.println(_("Exporting scores in ECATS format to ")+exportdir); exportdir = new File (".").getCanonicalPath(); if (null == exportdir) try { { public static void exportToECATS(List boards, List pairs, Map options, String exportdir) throws ScoreException } } } out.print("\r\n"); out.print("0"); //spare = 0 out.print("\t"); out.print("0"); //spare = 0 out.print("\t"); out.print(session); // session number again out.print("\t"); out.print('"'); } } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60"); case Hand.AVERAGE_PLUS: switch (b.getEWAverage()) { } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60"); case Hand.AVERAGE_PLUS: switch (b.getNSAverage()) { out.print("A"); if (b.isAveraged()) { out.print('"'); out.print("\t"); out.print(""+b.getEWMP()); // double, recalculated out.print("\t"); out.print(""+b.getNSMP()); // double, recalculatedadˆl4û¾{Z@#‹N76ú ù å Ù ® ‚ V  ý ö » | [ + ì Ñ ƒ P >  Ñ ” Y å Š  w r q - ( ëÒµ°¯qlûó„`B(í˰™fRQîØ¹tYXö×ÁX%ç‡qWÚ½¼U?Ê®­ { public static void x { public static void ximp(List boards) throws ScoreException } mo { public static void ximp(List { public static { public static void ximp(List boards) throws ScoreException } modifiedboards = true; { public static void xi { public static void ximp(List boards) throws Scor { public static void ximp(List boards) throws ScoreException { public static void { public static { public static void ximp(List boards) throws ScoreException } modifiedboards = { public static void ximp { public static void xim { public static void ximp(List boards) throws { public static void ximp(List boards) throws ScoreException { public static void ximp(List { public static { public static void ximp { public static void ximp(List boards) throws ScoreException } modifiedboards = tr { public static void { public static void ximp(List boards) throws ScoreException { public static void ximp { public static { public static void ximp(List boards) throws ScoreException } modifiedboards = tru { public stati { public static void ximp(List boards) throws { public static v { public static void { public static void ximp(Li { public static void ximp(List boards) { public { public static void { public static void xim { public static void ximp(List { public static void ximp(List boards) throws ScoreException } modifiedboards = true; { { { public static void ximp(List boards) throws ScoreException } modifiedboards = true; { public static void ximp(List boards) throws ScoreException } modifiedboards = true; b.matchPoint(); for (Board b: (Board[]) boards.toArray(new Board[0])) { public static void matchpoint(List boards) throws ScoreException } } } new Object[] { boards[i].getNumber(), h.getNS(), h.getEW() })); MessageFormat.format(_("Board {0} was played by {1} and {2}, which I was not expecting."), throw new MovementVerificationException( if (!pairs.contains(h.getNS()+" "+h.getEW())) for (Hand h: (Hand[]) boards[i].getHands().toArray(new Hand[0])) // check the pairs } else { pairs.add(h.getNS()+" "+h.getEW()); for (Hand h: (Hand[]) boards[i].getHands().toArray(new Hand[0])) pairs.clear(); // reset the pairs if (0 == (i % size)) { for (int i = 0; i < boards.length; i++) { Set pairs = new TreeSet(); Board[] boards = (Board[]) boardv.toArray(new Board[0]); Collections.sort(boardv, new BoardNumberComparer()); } throw new MovementVerificationException(setsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { size = Integer.parseInt(setsize); try { int size = 0; if (null == setsize || setsize.length() == 0) return; b.validate(); for (Board b: (Board[]) boardv.toArray(new Board[0])) { public static void verify(List boardv, String setsize) throws MovementVerificationException, BoardValidationException, HandParseException } modifiedboards = true; h.score(); if (!h.isAveraged()) for (Hand h: (Hand[]) b.getHands().toArray(new Hand[0])) for (Board b: (Board[]) boards.toArray(new Board[0])) {ad9Ñað“Žþȹ‰Z+å Ú Ù À ¥ g 6  ÿ ñ Ð È    \ 8 ´ œ o O ì § ‡ ; :  ÿ ú ù ¹ ´ w b E @ ?  ̲–‘ ò¾¯}NËÀ¿‹ŠOלdâÕba.ëäÏΨw.öÁ‹HÑÐ matrix[i][j+1] = format.format(boards[i+start].getMPs(pairs[j].getNumber()), tmp, field).toString(); if (boards[i+start].played(pairs[j].getNumber())) { StringBuffer tmp = new StringBuffer(); for (int j = 0; j < pairs.length; j++) { matrix[i][0] = boards[i+start].getNumber(); for (int i = 0; i+start < boards.length && i < grouping; i++) { float[] sums = new float[pairs.length]; while (start < boards.length) { int start = 0; String[][] matrix = new String[grouping+2][pairs.length+1]; if (0 == grouping) grouping = boards.length; headers[j+1] = pairs[j].getNumber()+" "; for (int j = 0; j < pairs.length; j++) headers[0] = _("Board"); String[] headers = new String[pairs.length+1]; FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.##"); Pair[] pairs = (Pair[]) pairv.toArray(new Pair[0]); Board[] boards = (Board[]) boardv.toArray(new Board[0]); Collections.sort(pairv, new PairNumberComparer()); Collections.sort(boardv, new BoardNumberComparer()); System.err.println("Grouping = " + grouping); } throw new MovementVerificationException(setsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { grouping = Integer.parseInt(setsize); try { if (null != setsize && setsize.length() >= 0) int grouping = 0; { public static void matrix(List pairv, List boardv, TablePrinter tabular, String setsize) throws MovementVerificationException } modifiedpairs = true; p.total(boards); for (Pair p: (Pair[]) pairs.toArray(new Pair[0])) { public static void total(List pairs, List boards) } modifiedboards = true; b.parimp(); for (Board b: (Board[]) boards.toArray(new Board[0])) { public static void parimp(List boards) throws ScoreException } tabular.gap(); tabular.print(headers, matrix); matrix[0][2] = format.format(usimps-themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][1] = format.format(themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][0] = format.format(usimps, tmp, field).toString(); tmp = new StringBuffer(); String[][] matrix = new String[1][3]; StringBuffer tmp; FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.##"); headers[2] = _("Difference"); headers[1] = _("Them IMPs"); headers[0] = _("Us IMPs"); String[] headers = new String[3]; } themimps += -res[0]; else usimps += res[0]; if (res[0] > 0) double[] res = b.sumimp(prefix, teams); for (Board b: (Board[]) boards.toArray(new Board[0])) { double themimps = 0; double usimps = 0; } throw new ScoreException(teamsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { teams = Integer.parseInt(teamsize); try { if (null != teamsize && teamsize.length() >= 0) int teams = 4; { public static void teams(List boards, TablePrinter tabular, String prefix, String teamsize) throws ScoreException } modifiedboards = true; b.ximp(); for (Board b: (Board[]) boards.toArray(new Board[0])) ad4Ä_µŸwi^3Ðmì ë  ª ¢ 7 2 õ à Ä ® • | l N /  â á £ } Y ! ä ¾ ‰ N 1 &  š Œ T  îæáà~yT+Ó°‚ËÀ«‰]ø¾žvU#þãØ¬ƒ{_Z÷òs9ûŸšWRÄà Collections.sort(pairs, new PairPercentageComparer()); // sort pairs in order int rate = (1 == Pair.getMaxNames()) ? 3 : 6; { public static void localpoint(List pairs) throws ScoreException } modifiedpairs = true; } p.setPercentage(p.getPercentage()-handicap+normalize); double handicap = (Double) handicaps.get(p); for (Pair p: (Pair[]) pairs.toArray(new Pair[0])) { if (null == handicaps) throw new ScoreException(_("Must supply a handicap file before calculating handicapped scores")); { public static void handicap(List pairs, Map handicaps, double normalize) throws ScoreException } return pairhandicaps; } pairhandicaps.put(p, handicap); handicap /= (double) names.length; } handicap += v; if (null == v) v = 50.0; Double v = (Double) handicaps.get(n); for (String n: names) { String[] names = p.getNames(); double handicap = 0.0; for (Pair p: (Pair[]) pairs.toArray(new Pair[0])) { } throw new ScoreException(_("Failure in reading handicap file: ")+IOe.getMessage()); if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { in.close(); } handicaps.put(values[0], new Double(values[1])); if (values.length != 2) throw new ScoreException(_("Malformed handicap line: ")+Arrays.deepToString(values)); String[] values = in.getValues(); while (in.readRecord()) { CsvReader in = new CsvReader(new InputStreamReader(handicapfile)); try { Map pairhandicaps = new HashMap(); Map handicaps = new HashMap(); { public static Map readHandicapData(List pairs, InputStream handicapfile) throws ScoreException } } tabular.gap(); tabular.print(headers, (String[][]) lines.toArray(new String[0][])); tabular.header(_("Board: ")+b.getNumber()); else tabular.header(_("Board: ")+b.getNumber()+" [ "+b.getParContract()+" by "+b.getPar().getDeclarer()+" ]"); if (withpar) } lines.add(line); System.arraycopy(ex, 1, line, 0, line.length); String[] line = new String[ex.length-1]; String[] ex = h.export(); for (Hand h: (Hand[]) hands.toArray(new Hand[0])) { Collections.sort(hands, new HandNSComparer()); List hands = b.getHands(); Vector lines = new Vector(); for (Board b: (Board[]) boards.toArray(new Board[0])) { Collections.sort(boards, new BoardNumberComparer()); "" }; : _("MPs:"), ximp ? _("IMPs") "", _("Score:"), _("Tricks"), _("By"), _("Contract"), _("EW"), _("NS"), String[] headers = new String[] { { public static void boardbyboard(List boards, TablePrinter tabular, boolean ximp, boolean withpar) } } tabular.gap(); tabular.print(headers, matrix); start += grouping; } matrix[matrix.length-1][j+1] = format.format(sums[j], tmp, field).toString(); matrix[matrix.length-2][j+1] = " "; StringBuffer tmp = new StringBuffer(); for (int j = 0; j < sums.length; j++) { matrix[matrix.length-1][0] = _("Total"); matrix[matrix.length-2][0] = " "; } } matrix[i][j+1] = " "; } else sums[j] += boards[i+start].getMPs(pairs[j].getNumber());ad5¹\ÉÈžçæ±‹VG"ë ª € ` È Œ i h A  ò Õ ‚ c - ý Õ ” k  ³ ’ ‡  c ^ ] ÙÔ¯rqL'æ×¶”^A9(úÚÂ|tbB7ÓÒÂ…`/̰¥š^98"ðÆ’a+îœih¹¸ if (Debug.debug) Debug.print("Printing handicap "+n[r.length-2]+" for "+p); n[r.length-2] = format.format(handicapdata.get(p), tmp, field).toString(); StringBuffer tmp = new StringBuffer(); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.#"); System.arraycopy(r, 0, n, 0, r.length-2); String[] n = new String[r.length+1]; String[] r = (String[]) results.get(i); Pair p = (Pair) pairs.get(i); for (int i = 0; i < pairs.size(); i++) { if (handicaps) results.add(p.export()); for (Pair p: (Pair[]) pairs.toArray(new Pair[0])) else } results.add(b); System.arraycopy(a, 5, b, 4, a.length-5); System.arraycopy(a, 0, b, 0, 4); String[] b = new String[a.length-1]; String[] a = p.export(); for (Pair p: (Pair[]) pairs.toArray(new Pair[0])) { if (ximp) String[] header = (String[]) headerv.toArray(new String[0]); headerv.add(_("LPs")); else headerv.add(_("OPs")); if (orange) } headerv.add(_("%age")); headerv.add(_("h'cap")); if (handicaps) headerv.add(_("MPs")); else { headerv.add(_("IMPs")); if (ximp) } headerv.add(""); for (int i = 1; i < Pair.getMaxNames(); i++) headerv.add(_("Names")); headerv.add(_("Pair")); } else { headerv.add(_("Name")); headerv.add(_("Num")); if (Pair.getMaxNames() == 1) { Vector headerv = new Vector(); Collections.sort(pairs, new PairPercentageComparer()); Vector results = new Vector(); { public static void results(List pairs, TablePrinter tabulate, boolean orange, boolean ximp, Map handicapdata, boolean handicaps) } modifiedpairs = true; } } ps[j].setLPs(award); new Object[] { award, ps[j].getNumber(), ps[j].getLPs() })); MessageFormat.format(_("Calculated {0} LPs for pair {1} but data says {2}."), throw new ScoreException( if (ps[j].getLPs() != 0 && ps[j].getLPs() != award) for (int j = a; j <= i; j++) { if (award < 6 && award > 0) award = 6; double award = Math.ceil(total / (1.0+i-a)); total += LPs[++i]; while (i+1 < ps.length && ps[i].getPercentage()==ps[i+1].getPercentage()) int total = LPs[i]; int a = i; for (int i = 0; i < ps.length && i < awarded; i++) { // award LPs, splitting on draws LPs[i] = lp > 6 ? lp : 6; for (int i = 0, lp=top; i < awarded; i++, lp -= rate) if (Debug.debug) Debug.print(Debug.DEBUG, "Awarding LPs to "+ps.length+" pairs, top is "+top+" rate is "+rate+" number receiving LPs: "+awarded); if (top > 100) top = 100; top = rate*awarded; } else top = (3 * (int) Math.ceil(tables/3.0)) + (3 * tables); int tables = (int) Math.floor(ps.length/4.0); if (1 == Pair.getMaxNames()) { int top; int awarded = (int) Math.ceil(LPs.length/3.0); int[] LPs = new int[ps.length]; // calculate LP scale based on number of pairs if (ps.length < ((1 == Pair.getMaxNames())?8:6)) throw new ScoreException(_("Must have at least 3 full tables at pairs or 2 full tables at individuals to award local points")); // check we have enough to give LPs Pair[] ps = (Pair[]) pairs.toArray(new Pair[0]);adç 3àÀ ŸrpÚÙ…„F3Oë À ž – ‘ V Q  è ¸ “ c 7  ô È Ç ¬ ¤ Ÿ ž e ` / ' Ù Ñ Ì Ë Ž ‰ X P õ í è ç q ¤ d ) ì±p String s; for (Board b: (Board[]) board String s; for (Board b: (Board[]) boards.toArray(n String s; for (Board b: (Board[]) boards.toA String s; for (Board b: (Board[]) boards.toArr String s; for (Board b: (Board[]) boards.toA Stri String s; for ( String s; for (Board b: (Board[]) boards.toArray(new Board[0])) { String s; for (Board b: (Board[]) boards.toArray(new Board[0])) { Buf String s; for (Board b: (Board[]) String s; for (Board b: (Board[]) boards.toArr String s; for (Board b: (Board[]) boards.toArray(new Board[0])) String s; for (Board b: (Board[]) String s; for (Board b: (Board[]) boards.t String s; fo String s; for (Board b: (Boar String s; for (Board b: String s; for String s; for (Board b: (Boar String s; for (Board b: (Board[]) String s; for (Board b String s; for (Board b: (Board[]) String s; for (Board b: (Board[]) String s; for (Board b: (Board[]) String s; for (Board b: (Board[]) boards.to String s; for (Boar String s; for (Board b: (Boa String s; for (Board b: (Boa String String s; for (Board b: (Board[]) boards.toArray(new Board[0])) { BufferedReader br = new BufferedReader(new InputStreamReader(trickdatafile)); Collections.sort(boards, new BoardNumberComparer()); { static void readTrickData(List boards, InputStream trickdatafile) throws IOException{public class Salliere implements Comparatorsimport java.text.MessageFormat;import java.text.FieldPosition;import java.text.DecimalFormat;salliere-0.10/cx/ath/matthew/salliere/ECatsOptionsMap.java0000644000175000017500000000506411317370537022231 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import java.util.HashMap; import static cx.ath.matthew.salliere.Gettext._; @SuppressWarnings("serial") public class ECatsOptionsMap extends HashMap { public static void printOptions() { System.out.println("ECATS options: "); System.out.println("\tclubName = name of club (required)"); System.out.println("\tsession = ECATS session number (required)"); System.out.println("\tphone = contact phone number (required)"); System.out.println("\tcountry = club country (required)"); System.out.println("\tname = contact name"); System.out.println("\tfax = contact fax number"); System.out.println("\temail = contact email"); System.out.println("\ttown = club town"); System.out.println("\tcounty = club county"); System.out.println("\tdate = event date"); System.out.println("\tevent = event name"); } public ECatsOptionsMap(String options) throws ScoreException { super(); put("name", ""); put("fax", ""); put("email", ""); put("town", ""); put("county", ""); put("date", ""); put("event", ""); if (null != options) { String[] opts = options.split(","); for (String o: opts) { String[] kv = o.split(":"); put(kv[0], kv[1]); } if (null == get("clubName")) throw new ScoreException(_("Required ECATS option not found: ")+"clubName"); if (null == get("session")) throw new ScoreException(_("Required ECATS option not found: ")+"session"); if (null == get("phone")) throw new ScoreException(_("Required ECATS option not found: ")+"phone"); if (null == get("country")) throw new ScoreException(_("Required ECATS option not found: ")+"country"); } } } salliere-0.10/cx/ath/matthew/salliere/MasterPointScale.java0000644000175000017500000001534711317407117022435 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import cx.ath.matthew.debug.Debug; import static cx.ath.matthew.salliere.Gettext._; public abstract class MasterPointScale { public static void printScales() { System.out.println("Available master point scales:"); System.out.println("\tA, Club = Club scale"); System.out.println("\tB, District = District scale"); System.out.println("\tC, County = County scale"); System.out.println("\tD, Regional = Regional scale"); System.out.println("\tE, National = National scale"); System.out.println("\tQA, Club Quali-Final = Club Quali-Final scale"); System.out.println("\tQB, District Quali-Final = District Quali-Final scale"); System.out.println("\tQC, County Quali-Final = County Quali-Final scale"); System.out.println("\tQD, Regional Quali-Final = Regional Quali-Final scale"); System.out.println("\tQE, National Quali-Final = National Quali-Final scale"); } public static MasterPointScale getScale(String scale) throws ScoreException { if (Debug.debug) Debug.print(Debug.INFO, "Using master point scale "+scale); if (null == scale) return new ClubScale(); String upscale = scale.toUpperCase(); // scale names in the handbook if ("A".equals(upscale)) return new ClubScale(); if ("B".equals(upscale)) return new DistrictScale(); if ("C".equals(upscale)) return new CountyScale(); if ("D".equals(upscale)) return new RegionalScale(); if ("E".equals(upscale)) return new NationalScale(); if ("QA".equals(upscale)) return new ClubQualiFinalScale(); if ("QB".equals(upscale)) return new DistrictQualiFinalScale(); if ("QC".equals(upscale)) return new CountyQualiFinalScale(); if ("QD".equals(upscale)) return new RegionalQualiFinalScale(); if ("QE".equals(upscale)) return new NationalQualiFinalScale(); // human-readable names if ("CLUB".equals(upscale)) return new ClubScale(); if ("DISTRICT".equals(upscale)) return new DistrictScale(); if ("COUNTY".equals(upscale)) return new CountyScale(); if ("REGIONAL".equals(upscale)) return new RegionalScale(); if ("NATIONAL".equals(upscale)) return new NationalScale(); if ("CLUB QUALI-FINAL".equals(upscale)) return new ClubQualiFinalScale(); if ("DISTRICT QUALI-FINAL".equals(upscale)) return new DistrictQualiFinalScale(); if ("COUNTY QUALI-FINAL".equals(upscale)) return new CountyQualiFinalScale(); if ("REGIONAL QUALI-FINAL".equals(upscale)) return new RegionalQualiFinalScale(); if ("NATIONAL QUALI-FINAL".equals(upscale)) return new NationalQualiFinalScale(); throw new ScoreException(_("Could not find master point scale: ")+scale); } public int minPairs(int pairsize) { return pairsize == 1 ? 8 : 6; } public int numberAwards(int pairs, int pairsize, int boards) { int arity = 1 == pairsize ? 4 : 2; double awards = (double) (pairs/arity); if (boards < 18) awards /= 4; else if (boards < 36) awards /= 3; else awards /= 2; return (int) Math.ceil(awards * arity); } public double getTop(int pairs, int pairsize, int boards) { return numberAwards(pairs, pairsize, boards) * getRate(pairsize); } public abstract int getMax(int boards); public abstract int getMin(); public abstract double getRate(int pairsize); } class ClubScale extends MasterPointScale { public int getMax(int boards) { if (boards < 12) return 0; if (boards < 18) return 75; if (boards < 36) return 100; return 300; } public int getMin() { return 6; } public double getRate(int pairsize) { return 1 == pairsize ? 3: 6; } } class DistrictScale extends MasterPointScale { public int getMax(int boards) { if (boards < 12) return 0; if (boards < 18) return 113; if (boards < 36) return 150; return 450; } public int getMin() { return 9; } public double getRate(int pairsize) { return 1 == pairsize ? 4.5: 9; } } class CountyScale extends MasterPointScale { public int getMax(int boards) { if (boards < 12) return 0; if (boards < 18) return 150; if (boards < 36) return 200; return 600; } public int getMin() { return 12; } public double getRate(int pairsize) { return 1 == pairsize ? 6: 12; } } class RegionalScale extends MasterPointScale { public int getMax(int boards) { if (boards < 12) return 0; if (boards < 18) return 225; if (boards < 36) return 300; return 900; } public int getMin() { return 18; } public double getRate(int pairsize) { return 1 == pairsize ? 9: 18; } } class NationalScale extends MasterPointScale { public int getMax(int boards) { if (boards < 12) return 0; if (boards < 18) return 300; if (boards < 36) return 400; return 1200; } public int getMin() { return 24; } public double getRate(int pairsize) { return 1 == pairsize ? 12: 24; } } abstract class QualiFinalScale extends MasterPointScale { public int numberAwards(int pairs, int pairsize, int boards) { int arity = 1 == pairsize ? 4 : 2; double awards = (double) (pairs/arity); awards /= 4; return (int) Math.ceil(awards * arity); } } class ClubQualiFinalScale extends QualiFinalScale { public int getMin() { return 6; } public double getRate(int pairsize) { return 1 == pairsize ? 5.5: 11; } public int getMax(int boards) { return 300; } } class DistrictQualiFinalScale extends QualiFinalScale { public int getMin() { return 9; } public double getRate(int pairsize) { return 1 == pairsize ? 8.25: 16.5; } public int getMax(int boards) { return 450; } } class CountyQualiFinalScale extends QualiFinalScale { public int getMin() { return 12; } public double getRate(int pairsize) { return 1 == pairsize ? 11: 22; } public int getMax(int boards) { return 600; } } class RegionalQualiFinalScale extends QualiFinalScale { public int getMin() { return 18; } public double getRate(int pairsize) { return 1 == pairsize ? 16.5: 33; } public int getMax(int boards) { return 900; } } class NationalQualiFinalScale extends QualiFinalScale { public int getMin() { return 24; } public double getRate(int pairsize) { return 1 == pairsize ? 22: 44; } public int getMax(int boards) { return 1200; } } salliere-0.10/cx/ath/matthew/salliere/.PDFTablePrinter.java.swp0000644000175000017500000003000011327147503023013 0ustar mjj29mjj29b0VIM 7.1¤ðÓI.mjj29qadesh~mjj29/scm/salliere/cx/ath/matthew/salliere/PDFTablePrinter.javautf-8 3210#"! UtpÿkadÖ–küØÔ®«`Ây,à • H ( % ó ð ì ë Ê É « ‰ ^ @  þ × Ö ³ ² › ~ e d / -  ï Ö ™ ” n R 8 3 û ö ê ¸   ~ K - 㧦ŒX*Þ½’‘zJêà›phc>9-Ö¯„|wb]Q'ÕÍȱ¬ nK1 ß×Òºµ˜–} } document.close(); { public void close() } } if (Debug.debug) Debug.print(De); } catch (DocumentException De) { document.open(); document.addTitle(title); PdfWriter.getInstance(document, output); try { { public void init() } } if (Debug.debug) Debug.print(De); } catch (DocumentException De) { document.add(new Paragraph("")); try { { public void gap() } } if (Debug.debug) Debug.print(De); } catch (DocumentException De) { document.add(new Paragraph(header, new Font(Font.HELVETICA, 16, Font.BOLD))); try { { public void header(String header) } } if (Debug.debug) Debug.print(De); } catch (DocumentException De) { document.add(table); table.addCell(rows[i][j]); for (int j = 0; j < rows[i].length; j++) for (int i = 0; i < rows.length; i++) // print rows } table.endHeaders(); table.addCell(cell); cell.setBorder(Table.BOTTOM); cell.setHeader(true); Cell cell = new Cell(headers[i]); for (int i = 0; i < headers.length; i++) { // print headers table.getDefaultCell().setBorder(Table.NO_BORDER); table.getDefaultCell().setVerticalAlignment(Table.ALIGN_MIDDLE); table.setPadding(2); table.setBorderColor(new Color(0, 0, 0)); table.setBorderWidth(1); table.setWidth(100); Table table = new Table(headers.length); try { { public void print(String[] headers, String[][] rows) } this.title = title; this.output = output; this.document = new Document(); { public PDFTablePrinter(String title, OutputStream output) private String title; private OutputStream output; private Document document;{public class PDFTablePrinter implements TablePrinterimport java.util.Arrays;import java.io.OutputStream;import java.awt.Color;import cx.ath.matthew.debug.Debug;import com.lowagie.text.pdf.PdfWriter;import com.lowagie.text.Table;import com.lowagie.text.Paragraph;import com.lowagie.text.Font;import com.lowagie.text.DocumentException;import com.lowagie.text.Document;import com.lowagie.text.Cell;package cx.ath.matthew.salliere; */ * * To Contact me, please email src@matthew.ath.cx * * Boston, MA 02111-1307, USA. * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * copy of the GNU General Public License along with this program; if not, * GNU General Public License for more details. You should have received a * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * the Free Software Foundation. This program is distributed in the hope that * under the terms of the GNU General Public License Version 2 as published by * This program is free software; you can redistribute it and/or modify it * * Copyright (C) 2007 Matthew Johnson * * Salliere Duplicate Bridge Scorer/* salliere-0.10/cx/ath/matthew/salliere/PDFTablePrinter.java0000644000175000017500000000615211327147503022140 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import com.lowagie.text.Cell; import com.lowagie.text.Document; import com.lowagie.text.DocumentException; import com.lowagie.text.Font; import com.lowagie.text.Paragraph; import com.lowagie.text.Table; import com.lowagie.text.pdf.PdfWriter; import cx.ath.matthew.debug.Debug; import java.awt.Color; import java.io.OutputStream; import java.util.Arrays; public class PDFTablePrinter implements TablePrinter { private Document document; private OutputStream output; private String title; public PDFTablePrinter(String title, OutputStream output) { this.document = new Document(); this.output = output; this.title = title; } public void print(String[] headers, String[][] rows) { try { Table table = new Table(headers.length); table.setWidth(100); table.setBorderWidth(1); table.setBorderColor(new Color(0, 0, 0)); table.setPadding(2); table.getDefaultCell().setVerticalAlignment(Table.ALIGN_MIDDLE); table.getDefaultCell().setBorder(Table.NO_BORDER); // print headers for (int i = 0; i < headers.length; i++) { Cell cell = new Cell(headers[i]); cell.setHeader(true); cell.setBorder(Table.BOTTOM); table.addCell(cell); table.endHeaders(); } // print rows for (int i = 0; i < rows.length; i++) for (int j = 0; j < rows[i].length; j++) table.addCell(rows[i][j]); document.add(table); } catch (DocumentException De) { if (Debug.debug) Debug.print(De); } } public void header(String header) { try { document.add(new Paragraph(header, new Font(Font.HELVETICA, 16, Font.BOLD))); } catch (DocumentException De) { if (Debug.debug) Debug.print(De); } } public void gap() { try { document.add(new Paragraph("")); } catch (DocumentException De) { if (Debug.debug) Debug.print(De); } } public void init() { try { PdfWriter.getInstance(document, output); document.addTitle(title); document.open(); } catch (DocumentException De) { if (Debug.debug) Debug.print(De); } } public void close() { document.close(); } } salliere-0.10/cx/ath/matthew/salliere/BoardValidationException.java0000644000175000017500000000174211306766510024136 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; @SuppressWarnings("serial") public class BoardValidationException extends Exception { public BoardValidationException(String message) { super(message); } } salliere-0.10/cx/ath/matthew/salliere/ContractParseException.java0000644000175000017500000000173611306766515023654 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; @SuppressWarnings("serial") public class ContractParseException extends Exception { public ContractParseException(String message) { super(message); } } salliere-0.10/cx/ath/matthew/salliere/MovementVerificationException.java0000644000175000017500000000175411306766525025242 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; @SuppressWarnings("serial") public class MovementVerificationException extends Exception { public MovementVerificationException(String message) { super(message); } } salliere-0.10/cx/ath/matthew/salliere/ScoreException.java0000644000175000017500000000171611306766535022157 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; @SuppressWarnings("serial") public class ScoreException extends Exception { public ScoreException(String message) { super(message); } } salliere-0.10/cx/ath/matthew/salliere/Individual.java0000644000175000017500000000563211306771607021312 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import cx.ath.matthew.debug.Debug; import java.util.List; import java.text.DecimalFormat; import java.text.FieldPosition; public class Individual extends Pair { String name = ""; public Individual() {} @SuppressWarnings("fallthrough") public Individual(String[] data) { this.number = data[0]; this.name = data[1]; switch (data.length) { case 5: if (0 < data[4].length()) lps = Double.parseDouble(data[4]); case 4: if (0 < data[3].length()) percentage = Double.parseDouble(data[3]); case 3: if (0 < data[2].length()) mps = Double.parseDouble(data[2]); } } public void total(List boards) { double top = 0; int bds = 0; mps = 0; for (Board b: boards) { top = b.getTop(); if (b.played(number)) { mps += b.getMPs(number); bds++; } } percentage = (mps*100) / (top*bds); if (Debug.debug) Debug.print("totalling for player "+number+": mps="+mps+", boards="+bds+", top="+top+", %age="+percentage); } public String[] getNames() { return new String[] { name, "" }; } public void setNames(String[] names) { this.name = names[0]; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append(number); sb.append(name); return sb.toString(); } public String[] export() { String[] rv = new String[5]; rv[0] = number; rv[1] = name; DecimalFormat format = new DecimalFormat("0.#"); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); StringBuffer tmp = new StringBuffer(); rv[2] = format.format(mps, tmp, field).toString(); tmp = new StringBuffer(); rv[4] = format.format(lps, tmp, field).toString(); format = new DecimalFormat("0.#"); tmp = new StringBuffer(); rv[3] = format.format(percentage, tmp, field).toString(); return rv; } } salliere-0.10/cx/ath/matthew/salliere/LeaderBoard.java0000644000175000017500000000461611306772750021367 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import cx.ath.matthew.debug.Debug; import static cx.ath.matthew.salliere.Gettext._; import java.text.DecimalFormat; import java.text.FieldPosition; import java.util.Arrays; import java.util.HashMap; public class LeaderBoard { class LeaderEntry implements Comparable { String name; double LPs; public LeaderEntry(String name, double LPs) { this.name = name; this.LPs = LPs; } public void update(double LPs) { this.LPs += LPs; } public int compareTo(Object o) { return (int) (((LeaderEntry) o).LPs - LPs); } } HashMap results = new HashMap(); public void update(String name, double LPs) { if (LPs == 0) return; LeaderEntry d = results.get(name); if (null == d) { d = new LeaderEntry(name, LPs); results.put(name, d); } else d.update(LPs); } public String[][] getLeaderBoard() { if (Debug.debug) Debug.print("Serializing leaderboard: "+results); String[][] results = new String[this.results.size()][2]; LeaderEntry[] es = this.results.values().toArray(new LeaderEntry[0]); Arrays.sort(es); int i = 0; for (LeaderEntry e: es) { results[i][0] = e.name; StringBuffer sb = new StringBuffer(); DecimalFormat format = new DecimalFormat("0.#"); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); results[i][1] = format.format(e.LPs, sb, field).toString(); i++; } return results; } } salliere-0.10/cx/ath/matthew/salliere/Leaders.java0000644000175000017500000000732111317355635020577 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import cx.ath.matthew.debug.Debug; import static cx.ath.matthew.salliere.Gettext._; import java.io.File; import java.io.FileInputStream; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Vector; public class Leaders { static void syntax() { String version = Package.getPackage("cx.ath.matthew.salliere") .getImplementationVersion(); System.out.println("Salliere Duplicate Bridge Scorer - version "+version); System.out.println("Usage: leaderboard "); } public static void main(String[] args) { try { if (Debug.debug) { File f = new File("debug.conf"); if (f.exists()) Debug.loadConfig(f); Debug.setThrowableTraces(true); } HashMap options = new HashMap(); options.put("--help", null); List files = new Vector(); int i; for (i = 0; i < args.length; i++) { if (args[i].startsWith("--")) { String[] opt = args[i].split("="); if (Debug.debug) Debug.print(Arrays.asList(opt)); if (options.containsKey(opt[0])) { if (opt.length == 1) options.put(opt[0], "true"); else options.put(opt[0], opt[1]); } else { System.out.println(_("Error: unknown option ")+opt[0]); syntax(); System.exit(1); } } else files.add(args[i]); } if (0 == files.size()) { System.out.println(_("You must specify at least one names file")); syntax(); System.exit(1); } if (null != options.get("--help")) { syntax(); System.exit(1); } TablePrinter printer = new AsciiTablePrinter(System.out); LeaderBoard leaders = new LeaderBoard(); for (String f: files) { System.out.println(f); List pairs = Salliere.readPairs(new FileInputStream(f), null); if (Debug.debug) Debug.print(Debug.DEBUG, "Got results: "+pairs); Salliere.results(pairs, printer, false, false, null, false); for (Pair p: pairs) { for (String s: p.getNames()) if (null != s && s.length() != 0) leaders.update(s, p.getLPs()); } printer.gap(); Pair.resetNames(); } printer.print(new String[] { _("Name"), _("Points") }, leaders.getLeaderBoard()); } catch (Exception e) { if (Debug.debug) { Debug.setThrowableTraces(true); Debug.print(e); } System.out.println(_("LeaderBoard failed: ")+e.getMessage()); System.exit(1); } } } salliere-0.10/cx/ath/matthew/salliere/GSalliere.java0000644000175000017500000013043711317403037021062 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import com.csvreader.CsvReader; import com.csvreader.CsvWriter; import cx.ath.matthew.debug.Debug; import static cx.ath.matthew.salliere.Gettext._; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.table.TableModel; import javax.swing.event.TableModelListener; public class GSalliere extends Salliere { @SuppressWarnings("serial") static class GSalliereMainFrame extends JFrame { @SuppressWarnings("serial") class BoardEditDialog extends JDialog implements ActionListener { private Board board; public BoardEditDialog(Board b) { super(GSalliereMainFrame.this, _("Edit Board ")+b.getNumber(), true); this.board = b; setDefaultCloseOperation(DISPOSE_ON_CLOSE); setContentPane(new JPanel(new BorderLayout())); JTable data = new JTable(new HandTableDataModel(b)); setSize(600, data.getRowHeight()*(b.getHands().size()+8)); add(new JScrollPane(data), BorderLayout.CENTER); JButton button = new JButton("OK"); button.addActionListener(this); add(button, BorderLayout.SOUTH); doLayout(); } public void actionPerformed(ActionEvent e) { dispose(); } } class BoardTableDataModel implements TableModel { private Board[] boards; public BoardTableDataModel(List boards) { if (null == boards) return; Collections.sort(boards, new BoardNumberComparer()); this.boards = boards.toArray(new Board[0]); } public int getRowCount() { return null == boards ? 1 : boards.length+1; } public int getColumnCount() { return 3; } public String getColumnName(int columnIndex) { switch (columnIndex) { case 0: return _("Number"); case 1: return _("Played"); case 2: return _("Pairs"); default: return _("ERR0R"); } } public Class getColumnClass(int columnIndex) { switch (columnIndex) { case 0: case 2: return String.class; case 1: return Integer.class; default: return null; } } public boolean isCellEditable(int rowIndex, int columnIndex) { return columnIndex==0; } public Object getValueAt(int rowIndex, int columnIndex) { if (null == boards) return ""; else if (rowIndex >= boards.length) return ""; else switch (columnIndex) { case 0: return boards[rowIndex].getNumber(); case 1: return boards[rowIndex].getHands().size(); case 2: Vector s = new Vector(); for (Hand h: boards[rowIndex].getHands()) { s.add(h.getNS()); s.add(h.getEW()); } return s.toString(); default: return ""; } } public void setValueAt(Object aValue, int rowIndex, int columnIndex) { if (null == boards) { GSalliere.boards = new Vector(); boards = new Board[1]; boards[0] = new Board(); rowIndex = 0; GSalliere.boards.add(boards[0]); } else if (rowIndex >= boards.length) { Board[] t = new Board[boards.length+1]; System.arraycopy(boards, 0, t, 0, boards.length); boards = t; rowIndex = boards.length-1; boards[rowIndex] = new Board(); GSalliere.boards.add(boards[rowIndex]); } switch (columnIndex) { case 0: boards[rowIndex].setNumber((String) aValue); break; default: break; } } public void addTableModelListener(TableModelListener l) {} public void removeTableModelListener(TableModelListener l) {} public Board getBoardAt(int row) { if (null == boards) return null; else if (row >= boards.length) return null; else return boards[row]; } } class HandTableDataModel implements TableModel { private Hand[] hands; private Board b; public HandTableDataModel(Board b) { this.b = b; List handv = b.getHands(); if (null == handv) return; Collections.sort(handv, new HandNSComparer()); this.hands = handv.toArray(new Hand[0]); } public int getRowCount() { return null == hands ? 1 : hands.length+1; } public int getColumnCount() { return 10; } public String getColumnName(int columnIndex) { switch (columnIndex) { case 0: return _("Number"); case 1: return _("NS"); case 2: return _("EW"); case 3: return _("Contract"); case 4: return _("By"); case 5: return _("Tricks"); case 6: return _("Score NS"); case 7: return _("Score EW"); case 8: return _("MP NS"); case 9: return _("MP EW"); default: return _("ERR0R"); } } public Class getColumnClass(int columnIndex) { switch (columnIndex) { case 0: case 1: case 2: case 3: case 4: case 6: case 7: return String.class; case 5: return Integer.class; case 8: case 9: return Double.class; default: return null; } } public boolean isCellEditable(int rowIndex, int columnIndex) { return columnIndex > 0; } public Object getValueAt(int rowIndex, int columnIndex) { if (null == hands || rowIndex >= hands.length) switch (columnIndex) { case 0: case 1: case 2: case 3: return ""; case 4: return ' '; case 5: return 0; case 6: case 7: case 8: case 9: return 0.0; default: return null; } else switch (columnIndex) { case 0: return hands[rowIndex].getNumber(); case 1: return hands[rowIndex].getNS(); case 2: return hands[rowIndex].getEW(); case 3: return hands[rowIndex].getContract(); case 4: return hands[rowIndex].getDeclarer(); case 5: return hands[rowIndex].getTricks(); case 6: switch (hands[rowIndex].getNSAverage()) { case Hand.AVERAGE: return "av="; case Hand.AVERAGE_PLUS: return "av+"; case Hand.AVERAGE_MINUS: return "av-"; default: return hands[rowIndex].getNSScore(); } case 7: switch (hands[rowIndex].getEWAverage()) { case Hand.AVERAGE: return "av="; case Hand.AVERAGE_PLUS: return "av+"; case Hand.AVERAGE_MINUS: return "av-"; default: return hands[rowIndex].getEWScore(); } case 8: return hands[rowIndex].getNSMP(); case 9: return hands[rowIndex].getEWMP(); default: return null; } } public void setValueAt(Object aValue, int rowIndex, int columnIndex) { try { if (null == hands) { hands = new Hand[1]; hands[0] = new Hand(); rowIndex = 0; b.addHand(hands[0]); } else if (rowIndex >= hands.length) { Hand[] t = new Hand[hands.length+1]; System.arraycopy(hands, 0, t, 0, hands.length); hands = t; rowIndex = hands.length-1; hands[rowIndex] = new Hand(); b.addHand(hands[rowIndex]); } switch (columnIndex) { case 1: hands[rowIndex].setNS((String) aValue); break; case 2: hands[rowIndex].setEW((String) aValue); break; case 3: hands[rowIndex].setContract((String) aValue); break; case 4: for (int i = 0; i < ((String) aValue).length(); i++) if (((String) aValue).charAt(i) != ' ') hands[rowIndex].setDeclarer(((String) aValue).charAt(i)); break; case 5: hands[rowIndex].setTricks((Integer) aValue); break; case 6: hands[rowIndex].setNSScore((String) aValue); hands[rowIndex].setForcedNSScore(true); break; case 7: hands[rowIndex].setEWScore((String) aValue); hands[rowIndex].setForcedEWScore(true); break; case 8: hands[rowIndex].setNSMP((Double) aValue); hands[rowIndex].setForcedNSMP(true); break; case 9: hands[rowIndex].setEWMP((Double) aValue); hands[rowIndex].setForcedEWMP(true); break; default: break; } } catch (HandParseException HPe) { if (Debug.debug) Debug.print(HPe); showerror(_("Problem while entering score: ")+HPe); } catch (BoardValidationException BVe) { if (Debug.debug) Debug.print(BVe); showerror(_("Problem while exporting: ")+BVe); } } public void addTableModelListener(TableModelListener l) {} public void removeTableModelListener(TableModelListener l) {} } class PairTableDataModel implements TableModel { private Pair[] pairs; public PairTableDataModel(List pairs) { if (null == pairs) return; Collections.sort(pairs, new PairNumberComparer()); this.pairs = pairs.toArray(new Pair[0]); } public int getRowCount() { return null == pairs ? 1 : pairs.length+1; } public int getColumnCount() { return 6; } public String getColumnName(int columnIndex) { switch (columnIndex) { case 0: return _("Number"); case 1: return _("Names"); case 2: return ""; case 3: return _("Match Points"); case 4: return _("Percentage"); case 5: return _("Local Points"); default: return _("ERR0R"); } } public Class getColumnClass(int columnIndex) { switch (columnIndex) { case 0: case 1: case 2: return String.class; case 3: case 4: case 5: return Double.class; default: return null; } } public boolean isCellEditable(int rowIndex, int columnIndex) { return true; } public Object getValueAt(int rowIndex, int columnIndex) { if (null == pairs) return columnIndex > 2 ? 0.0 : ""; else if (rowIndex >= pairs.length) return columnIndex > 2 ? 0.0 : ""; else switch (columnIndex) { case 0: return pairs[rowIndex].getNumber(); case 1: return pairs[rowIndex].getNames()[0]; case 2: return pairs[rowIndex].getNames()[1]; case 3: return pairs[rowIndex].getMPs(); case 4: return pairs[rowIndex].getPercentage(); case 5: return pairs[rowIndex].getLPs(); default: return null; } } public void setValueAt(Object aValue, int rowIndex, int columnIndex) { if (null == pairs) { GSalliere.pairs = new Vector(); pairs = new Pair[1]; pairs[0] = new Pair(); rowIndex = 0; GSalliere.pairs.add(pairs[0]); } else if (rowIndex >= pairs.length) { Pair[] t = new Pair[pairs.length+1]; System.arraycopy(pairs, 0, t, 0, pairs.length); pairs = t; rowIndex = pairs.length-1; pairs[rowIndex] = new Pair(); GSalliere.pairs.add(pairs[rowIndex]); } switch (columnIndex) { case 0: pairs[rowIndex].setNumber((String) aValue); break; case 1: String[] names = pairs[rowIndex].getNames(); names[0] = (String) aValue; pairs[rowIndex].setNames(names); break; case 2: names = pairs[rowIndex].getNames(); names[1] = (String) aValue; pairs[rowIndex].setNames(names); break; case 3: pairs[rowIndex].setMPs((Double) aValue); break; case 4: pairs[rowIndex].setPercentage((Double) aValue); break; case 5: pairs[rowIndex].setLPs((Double) aValue); break; default: break; } } public void addTableModelListener(TableModelListener l) {} public void removeTableModelListener(TableModelListener l) {} } class MenuActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (Debug.debug) Debug.print("Menu Action: "+command); if ("loadscores".equals(command)) { status.setText(_("Loading Boards...")); JFileChooser fc; if (null == boardfile) fc = new JFileChooser(); else fc = new JFileChooser(new File(boardfile).getParent()); if (Debug.debug) Debug.print("Showing File Chooser"); int rv = fc.showOpenDialog(GSalliereMainFrame.this); if (rv == JFileChooser.APPROVE_OPTION) { if (Debug.debug) Debug.print("Approved, file="+fc.getSelectedFile()); File f = fc.getSelectedFile(); try { boardfile = f.getCanonicalPath(); status.setText(_("Loading Boards from ")+boardfile); boards = readBoards(new FileInputStream(f)); boardtable.setModel(new BoardTableDataModel(boards)); status.setText(_("Loaded Boards from ")+boardfile); } catch (IOException IOe) { if (Debug.debug) Debug.print(IOe); showerror(_("Problem loading boards file: ")+IOe); boards = null; } catch (BoardValidationException BVe) { if (Debug.debug) Debug.print(BVe); showerror(_("Problem loading boards file: ")+BVe); boards = null; } } else { if (Debug.debug) Debug.print("chooser returned "+rv); } } else if ("loadnames".equals(command)) { status.setText(_("Loading Names...")); JFileChooser fc; if (null != namesfile) fc = new JFileChooser(new File(namesfile).getParent()); else if (null != boardfile) fc = new JFileChooser(new File(boardfile).getParent()); else fc = new JFileChooser(); int rv = fc.showOpenDialog(GSalliereMainFrame.this); if (rv == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); try { namesfile = f.getCanonicalPath(); status.setText(_("Loading Names from ")+namesfile); pairs = readPairs(new FileInputStream(f), boards); nametable.setModel(new PairTableDataModel(pairs)); status.setText(_("Loaded Names from ")+namesfile); } catch (IOException IOe) { if (Debug.debug) Debug.print(IOe); showerror(_("Problem loading names file: ")+IOe); pairs = null; } } } else if ("loadtricks".equals(command)) { status.setText(_("Loading Tricks...")); if (null == boards) showerror(_("Must Load Boards before loading trick data")); else { JFileChooser fc; if (null == boardfile) fc = new JFileChooser(); else fc = new JFileChooser(new File(boardfile).getParent()); int rv = fc.showOpenDialog(GSalliereMainFrame.this); if (rv == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); try { namesfile = f.getCanonicalPath(); status.setText(_("Loading Tricks from ")+namesfile); readTrickData(boards, new FileInputStream(f)); nametable.setModel(new PairTableDataModel(pairs)); status.setText(_("Loaded Tricks from ")+namesfile); } catch (IOException IOe) { if (Debug.debug) Debug.print(IOe); showerror(_("Problem loading names file: ")+IOe); pairs = null; } } } } else if ("savescores".equals(command)) { if (null == boards) showerror(_("Must Load Boards before saving them")); else { status.setText(_("Saving Boards")); JFileChooser fc; if (null == boardfile) fc = new JFileChooser(); else fc = new JFileChooser(new File(boardfile).getParent()); int rv = fc.showSaveDialog(GSalliereMainFrame.this); if (rv == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); try { boardfile = f.getCanonicalPath(); status.setText(_("Saving Boards to ")+boardfile); writeBoards(boards, new FileOutputStream(f)); status.setText(_("Saved Boards to ")+boardfile); } catch (IOException IOe) { if (Debug.debug) Debug.print(IOe); showerror(_("Problem saving boards file: ")+IOe); } } } } else if ("savenames".equals(command)) { if (null == pairs) showerror(_("Must Load Pairs before saving them")); else { status.setText(_("Saving Names")); JFileChooser fc; if (null == namesfile) fc = new JFileChooser(); else fc = new JFileChooser(new File(namesfile).getParent()); int rv = fc.showSaveDialog(GSalliereMainFrame.this); if (rv == JFileChooser.APPROVE_OPTION) { File f = fc.getSelectedFile(); try { namesfile = f.getCanonicalPath(); status.setText(_("Saving Names to ")+namesfile); writePairs(pairs, new FileOutputStream(f)); status.setText(_("Saved Names to ")+namesfile); } catch (IOException IOe) { if (Debug.debug) Debug.print(IOe); showerror(_("Problem saving names file: ")+IOe); } } } } else if ("export".equals(command)) { status.setText(_("Exporting results")); if (null == pairs || null == boards) showerror(_("Must Load Pairs and boards before exporting")); else export(GSalliereMainFrame.this); } else if ("ecats-upload".equals(command)) { status.setText(_("Uploading results to ECATS")); if (null == pairs || null == boards) showerror(_("Must Load Pairs and boards before uploading to ECATS")); else { ECATSDialog d = new ECATSDialog(GSalliereMainFrame.this, pairs, boards, true); d.setVisible(true); } } else if ("ecats-export".equals(command)) { status.setText(_("Exporting results for ECATS")); if (null == pairs || null == boards) showerror(_("Must Load Pairs and boards before uploading to ECATS")); else { ECATSDialog d = new ECATSDialog(GSalliereMainFrame.this, pairs, boards, false); d.setVisible(true); } } else if ("quit".equals(command)) { setVisible(false); System.exit(0); } } } class ButtonActionListener implements ActionListener { private JTextField setsize; public ButtonActionListener(JTextField setsize) { this.setsize = setsize; } public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); try { if ("score".equals(command)) { status.setText(_("Scoring boards")); if (null == boards) showerror(_("Must Load Boards before Scoring")); else score(boards); } else if ("matchpoint".equals(command)) { status.setText(_("Matchpointing boards")); if (null == boards) showerror(_("Must Load Boards before Matchpointing")); else matchpoint(boards); } else if ("ximp".equals(command)) { status.setText(_("XIMPing boards")); if (null == boards) showerror(_("Must Load Boards before XIMPing")); else ximp(boards); } else if ("parimp".equals(command)) { status.setText(_("IMPing boards against par")); if (null == boards) showerror(_("Must Load Boards before IMPing")); else parimp(boards); } else if ("total".equals(command)) { status.setText(_("Calculating total matchpoints and percentages")); if (null == boards || null == pairs) showerror(_("Must Load Boards and Pairs before Totalling")); else total(pairs, boards); nametable.repaint(); } else if ("localpoint".equals(command)) { status.setText(_("Allocating local points")); if (null == pairs) showerror(_("Must Load Pairs before allocating local points")); if (null == boards) showerror(_("Must Load Boards before allocating local points")); else localpoint(pairs, boards, MasterPointScale.getScale(null), -1); nametable.repaint(); } else if ("results".equals(command)) { status.setText(_("Exporting results")); if (null == boards || null == pairs) showerror(_("Must Load Boards and Pairs before exporting results")); else export(GSalliereMainFrame.this); } else if ("validate".equals(command)) { status.setText(_("Verifying Movement")); if (null == boards) showerror(_("Must Load Boards before Verifying movement")); else verify(boards, setsize.getText()); } } catch (ScoreException Se) { if (Debug.debug) Debug.print(Se); showerror(_("Problem while performing action: ")+Se); } catch (ContractParseException CPe) { if (Debug.debug) Debug.print(CPe); showerror(_("Problem while performing action: ")+CPe); } catch (BoardValidationException BVe) { if (Debug.debug) Debug.print(BVe); showerror(_("Problem validating boards: ")+BVe); } catch (MovementVerificationException MVe) { if (Debug.debug) Debug.print(MVe); showerror(_("Problem while performing action: ")+MVe); } catch (HandParseException HPe) { if (Debug.debug) Debug.print(HPe); showerror(_("Problem while performing action: ")+HPe); } } } class MouseActionListener implements MouseListener { @SuppressWarnings("deprecation") public void mouseClicked(MouseEvent e) { if (Debug.debug) Debug.print(e); int y = e.getY(); JTable table = (JTable) e.getSource(); int row = y / table.getRowHeight(); if (Debug.debug) Debug.print("Clicked on row "+row); Board b = ((BoardTableDataModel) table.getModel()).getBoardAt(row); if (null != b) { BoardEditDialog bed = new BoardEditDialog(b); bed.show(); table.repaint(); } } public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} } @SuppressWarnings("serial") public class ECATSDialog extends JDialog implements ActionListener { GSalliereMainFrame gs; List pairs; List boards; boolean upload; // fields JTextField clubName = new JTextField(); JTextField session = new JTextField(); JTextField phone = new JTextField(); JTextField country = new JTextField(); JTextField name = new JTextField(); JTextField fax = new JTextField(); JTextField email = new JTextField(); JTextField town = new JTextField(); JTextField county = new JTextField(); JTextField date = new JTextField(); JTextField event = new JTextField(); JTextField path = new JTextField(); public ECATSDialog(GSalliereMainFrame gs, List pairs, List boards, boolean upload) { this.gs = gs; this.pairs = pairs; this.boards = boards; this.upload = upload; setSize(600,200); setLayout(new BorderLayout()); // add sub-panels JPanel left = new JPanel(); JPanel right = new JPanel(); JPanel bottom = new JPanel(); add(left, BorderLayout.WEST); add(right, BorderLayout.EAST); add(bottom, BorderLayout.SOUTH); // left panel (mandatory fields) left.setLayout(new GridLayout(0,2)); left.add(new JLabel(_("Mandatory"))); left.add(new JLabel(_("Fields"))); left.add(new JLabel(_("Session"))); left.add(session); left.add(new JLabel(_("Club Name"))); left.add(clubName); left.add(new JLabel(_("Country"))); left.add(country); left.add(new JLabel(_("Contact Name"))); left.add(name); left.add(new JLabel(_("Contact Email"))); left.add(email); left.add(new JLabel(_("Contact Phone Number"))); left.add(phone); // right panel (optional fields) right.setLayout(new GridLayout(0,2)); right.add(new JLabel(_("Optional"))); right.add(new JLabel(_("Fields"))); right.add(new JLabel(_("Date"))); right.add(date); right.add(new JLabel(_("Event"))); right.add(event); right.add(new JLabel(_("Town"))); right.add(town); right.add(new JLabel(_("County"))); right.add(county); right.add(new JLabel(_("Contact Fax Number"))); right.add(fax); // bottom panel (path and button) bottom.setLayout(new BoxLayout(bottom, BoxLayout.Y_AXIS)); JButton confirm; if (!upload) { bottom.add(new JLabel(_("Directory to export to"))); bottom.add(path); confirm = new JButton(_("Export to ECATS format")); } else confirm = new JButton(_("Upload to ECATS")); confirm.addActionListener(this); bottom.add(confirm); } public void actionPerformed(ActionEvent e) { setVisible(false); Map options = new HashMap(); options.put("clubName", clubName.getText()); options.put("session", session.getText()); options.put("phone", phone.getText()); options.put("country", country.getText()); options.put("name", name.getText()); options.put("fax", fax.getText()); options.put("email", email.getText()); options.put("town", town.getText()); options.put("county", county.getText()); options.put("date", date.getText()); options.put("event", event.getText()); try { if (upload) { status.setText(_("Uploading scores to ECATS")); uploadToECATS(boards, pairs, options); } else { status.setText(_("Exporting scores in ECATS format to ")+path.getText()); exportToECATS(boards, pairs, options, path.getText()); JOptionPane.showMessageDialog(gs, "ECATS files have been written to `"+path.getText()+"'. Email the files C.txt, P.txt, R.txt and E.txt to results@simpairs.com", _("ECATS"), JOptionPane.INFORMATION_MESSAGE); } } catch (ScoreException Se) { if (Debug.debug) Debug.print(Se); showerror(_("Problem exporting to ECATS: ")+Se); } } } private JPanel body; private JLabel status; private JTable boardtable; private JTable nametable; public GSalliereMainFrame() { super(_("GSalliere - Duplicate Bridge Scoring")); setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); /* MENU */ JMenuBar menuBar = new JMenuBar(); menuBar.setVisible(true); setJMenuBar(menuBar); setContentPane(new JPanel(new BorderLayout())); // file menu JMenu file = new JMenu(_("File")); file.setMnemonic(KeyEvent.VK_F); file.getAccessibleContext().setAccessibleDescription( _("Has options to load and save score files and export results")); menuBar.add(file); JMenuItem item; ActionListener mal = new MenuActionListener(); // load score file item = new JMenuItem(_("Load Score File"), KeyEvent.VK_L); item.setActionCommand("loadscores"); item.addActionListener(mal); file.add(item); // load names file item = new JMenuItem(_("Load Names File"), KeyEvent.VK_N); item.setActionCommand("loadnames"); item.addActionListener(mal); file.add(item); // load tricks file item = new JMenuItem(_("Load Tricks File"), KeyEvent.VK_T); item.setActionCommand("loadtricks"); item.addActionListener(mal); file.add(item); // save score file item = new JMenuItem(_("Save Score File"), KeyEvent.VK_S); item.setActionCommand("savescores"); item.addActionListener(mal); file.add(item); // save names file item = new JMenuItem(_("Save Names File"), KeyEvent.VK_A); item.setActionCommand("savenames"); item.addActionListener(mal); file.add(item); // export results item = new JMenuItem(_("Export Results"), KeyEvent.VK_E); item.setActionCommand("export"); item.addActionListener(mal); file.add(item); // ECATS item = new JMenuItem(_("Upload Results to ECATS"), KeyEvent.VK_U); item.setActionCommand("ecats-upload"); item.addActionListener(mal); file.add(item); item = new JMenuItem(_("Export in ECATS format"), KeyEvent.VK_C); item.setActionCommand("ecats-export"); item.addActionListener(mal); file.add(item); // quit item = new JMenuItem(_("Quit"), KeyEvent.VK_Q); item.setActionCommand("quit"); item.addActionListener(mal); file.add(item); /* MAIN BODY */ body = new JPanel(); body.setLayout(new BoxLayout(body, BoxLayout.Y_AXIS)); body.setVisible(true); add(body, BorderLayout.CENTER); body.add(new JLabel(_("Pairs"))); MouseListener moal = new MouseActionListener(); nametable = new JTable(new PairTableDataModel(null)); nametable.setVisible(true); body.add(new JScrollPane(nametable)); if (null != pairs) nametable.setModel(new PairTableDataModel(pairs)); body.add(new JLabel(_("Boards"))); boardtable = new JTable(new BoardTableDataModel(null)); boardtable.addMouseListener(moal); boardtable.setVisible(true); body.add(new JScrollPane(boardtable)); if (null != boards) boardtable.setModel(new BoardTableDataModel(boards)); /* BUTTON BAR 1 */ JPanel buttonbarholder = new JPanel(); buttonbarholder.setLayout(new BoxLayout(buttonbarholder, BoxLayout.Y_AXIS)); add(buttonbarholder, BorderLayout.NORTH); JPanel buttonbar = new JPanel(new FlowLayout()); buttonbar.setVisible(true); buttonbarholder.add(buttonbar); JButton button; JTextField setsize = new JTextField(2); ActionListener bal = new ButtonActionListener(setsize); // score button = new JButton(_("Score")); button.setToolTipText(_("Score the contracts")); button.setActionCommand("score"); button.setMnemonic(KeyEvent.VK_S); button.addActionListener(bal); buttonbar.add(button); // matchpoint button = new JButton(_("Match Point")); button.setToolTipText(_("Matchpoint the boards")); button.setActionCommand("matchpoint"); button.setMnemonic(KeyEvent.VK_M); button.addActionListener(bal); buttonbar.add(button); // ximp button = new JButton(_("XIMP")); button.setToolTipText(_("Cross-IMP the boards")); button.setActionCommand("ximp"); button.setMnemonic(KeyEvent.VK_X); button.addActionListener(bal); buttonbar.add(button); // parimp button = new JButton(_("IMP-Par")); button.setToolTipText(_("IMP the boards against par")); button.setActionCommand("parimp"); button.setMnemonic(KeyEvent.VK_P); button.addActionListener(bal); buttonbar.add(button); // total button = new JButton(_("Total")); button.setToolTipText(_("Total the match points for the pairs")); button.setActionCommand("total"); button.setMnemonic(KeyEvent.VK_T); button.addActionListener(bal); buttonbar.add(button); // localpoint button = new JButton(_("Local Point")); button.setToolTipText(_("Calculate local points for the pairs")); button.setActionCommand("localpoint"); button.setMnemonic(KeyEvent.VK_M); button.addActionListener(bal); buttonbar.add(button); // results button = new JButton(_("Results")); button.setToolTipText(_("Export the Results")); button.setActionCommand("results"); button.setMnemonic(KeyEvent.VK_R); button.addActionListener(bal); buttonbar.add(button); /* BUTTON BAR 2 */ buttonbar = new JPanel(new FlowLayout()); buttonbar.setVisible(true); buttonbarholder.add(buttonbar); // validate buttonbar.add(new JLabel(_("Set Size:"))); buttonbar.add(setsize); button = new JButton(_("Validate")); button.setToolTipText(_("Validate the movement")); button.setActionCommand("validate"); button.setMnemonic(KeyEvent.VK_V); button.addActionListener(bal); buttonbar.add(button); // save button = new JButton(_("Save")); button.setToolTipText(_("Save both files")); button.setActionCommand("save"); button.setMnemonic(KeyEvent.VK_A); button.addActionListener(bal); buttonbar.add(button); /* STATUS BAR */ status = new JLabel(); status.setVisible(true); add(status, BorderLayout.SOUTH); pack(); } public void showerror(String text) { status.setText(_("Error: ")+text); JOptionPane.showMessageDialog(this, text, _("Error"), JOptionPane.ERROR_MESSAGE); } } public static void export(GSalliereMainFrame root) { JFileChooser fc = new JFileChooser(); JPanel accessories = new JPanel(); accessories.setLayout(new BoxLayout(accessories, BoxLayout.Y_AXIS)); fc.setAccessory(accessories); JTextField title = new JTextField(); ButtonGroup format = new ButtonGroup(); JRadioButton textformat = new JRadioButton(_("Text"), true); textformat.setActionCommand("Text"); format.add(textformat); JRadioButton htmlformat = new JRadioButton(_("HTML"), true); htmlformat.setActionCommand("HTML"); format.add(htmlformat); JRadioButton pdfformat = new JRadioButton(_("PDF"), true); pdfformat.setActionCommand("PDF"); format.add(pdfformat); JCheckBox results = new JCheckBox(_("Results"), true); JCheckBox matrix = new JCheckBox(_("MP Matrix")); JCheckBox boardby = new JCheckBox(_("Board-by-boards")); JCheckBox orange = new JCheckBox(_("Orange Points")); JCheckBox ximp = new JCheckBox("IMP"); JCheckBox par = new JCheckBox(_("Show Par")); accessories.add(new JLabel(_("Title: "))); accessories.add(title); accessories.add(textformat); accessories.add(htmlformat); accessories.add(pdfformat); accessories.add(results); accessories.add(matrix); accessories.add(boardby); accessories.add(orange); accessories.add(ximp); accessories.add(par); int rv = fc.showDialog(root, _("Export")); if (rv == JFileChooser.APPROVE_OPTION) { File exportfile = fc.getSelectedFile(); String titlestr = title.getText(); boolean orangebool = orange.isSelected(); boolean ximpbool = ximp.isSelected(); boolean parbool = par.isSelected(); String command = format.getSelection().getActionCommand(); if (Debug.debug) Debug.print("Exporting to "+exportfile+" command="+command); try { FileOutputStream out = new FileOutputStream(exportfile); TablePrinter tabular = null; if ("Text".equals(command)) tabular = new AsciiTablePrinter(new PrintStream(out)); else if ("HTML".equals(command)) tabular = new HTMLTablePrinter(titlestr, new PrintStream(out)); else if ("PDF".equals(command)) tabular = new PDFTablePrinter(titlestr, out); tabular.init(); tabular.header(titlestr); if (results.isSelected()) results(pairs, tabular, orangebool, ximpbool, null, false); if (matrix.isSelected()) matrix(pairs, boards, tabular, null); if (boardby.isSelected()) boardbyboard(boards, tabular, ximpbool, parbool); tabular.close(); out.close(); } catch (Exception e) { if (Debug.debug) Debug.print(e); root.showerror(_("Problem while exporting: ")+e); } } } private static List boards; private static String boardfile; private static String namesfile; private static String outputfile; private static List pairs; public static void main(String[] args) { try { if (Debug.debug) Debug.setThrowableTraces(true); if (args.length == 2) { boardfile = new File(args[0]).getCanonicalPath(); namesfile = new File(args[1]).getCanonicalPath(); try { boards = readBoards(new FileInputStream(boardfile)); } catch (IOException IOe) { if (Debug.debug) Debug.print(IOe); System.out.println(_("Problem loading boards file: ")+IOe); boards = null; } try { pairs = readPairs(new FileInputStream(namesfile), boards); } catch (IOException IOe) { if (Debug.debug) Debug.print(IOe); System.out.println(_("Problem loading names file: ")+IOe); pairs = null; } } GSalliereMainFrame main = new GSalliereMainFrame(); main.setVisible(true); } catch (Exception e) { if (Debug.debug) Debug.print(e); System.out.println(_("There was a problem during the execution of GSalliere: ")+e.getMessage()); System.exit(1); } } } salliere-0.10/cx/ath/matthew/salliere/.Salliere.java.swl0000644000175000017500000017000011327115661021627 0ustar mjj29mjj29b0VIM 7.1§›\K})¯:mjj29qadesh~mjj29/scm/salliere/cx/ath/matthew/salliere/Salliere.javautf-8 3210#"! Utp ÿln ap aÑ]2fiõd^k \- c‰ Jì6ad€DlüØÔ®«`Ây,à • H ( % ó ð ì ë Ê É © ‰ ˆ e 4 3   æ É ´ ” s W 5  ü Ù ½ ¡ ˆ j M 3   ð Ö ½ } ] \ F D Ì‘TÙØ˜kcAýõðﮩzrL&Ñ¥‰b65  ÍÈ›“WOJIÔÌ1-œD3  Ø if (hands1.size() == 0 || hands2.size() == 0) { List if (ob2.getMPs() != ob1.getMPs()) ret if (ob2.getMPs() != ob1.getMPs()) return (int)((ob2.getMPs()-ob1.getMPs())*10000.0); if (ob2.getPercentage() != ob1.getPercentage()) return (int) ((ob2.getPercentage()-ob1.getPercentage())*10000.0); // no need to split tie if (Debug.debug) Debug.print(Debug.VERBOSE, "Comparing "+ob1.getNumber()+"["+ob1.getPercentage()+"] and "+ob2.getNumber()+"["+ob2.getPercentage()+"]"); { public int compare(Pair ob1, Pair ob2) { static class PairPercentageComparer implements Comparator } } return ob1.getNumber().compareTo(ob2.getNumber()); { public int compare(Pair ob1, Pair ob2) { static class PairNumberComparer implements Comparator } } return num1-num2; int num2 = Integer.parseInt(v[0]); v = n[n.length-1].split(";"); n = n2.split(":"); int num1 = Integer.parseInt(v[0]); String[] v = n[n.length-1].split(";"); String[] n = n1.split(":"); String n2 = ob2.getNumber(); String n1 = ob1.getNumber(); { public int compare(Board ob1, Board ob2) { static class BoardNumberComparer implements Comparator } } return n1.compareTo(n2); String n2 = ob2.getNS(); String n1 = ob1.getNS(); { public int compare(Hand ob1, Hand ob2) { static class HandNSComparer implements Comparator public static final String ECATS_PROGRAM_VERSION = "5.6.28"; public static final String ECATS_UPLOAD_DIR = "\\sims"; public static final String ECATS_PASSWORD = "simsuser32"; public static final String ECATS_USERNAME = "simsuser"; public static final String ECATS_SERVER = "sims.ecats.co.uk"; // data gathered from looking at ecats-ftp sessions{public class Salliereimport java.text.MessageFormat;import java.text.FieldPosition;import java.text.DecimalFormat;import java.util.Vector;import java.util.TreeSet;import java.util.Set;import java.util.Map;import java.util.List;import java.util.HashMap;import java.util.Comparator;import java.util.Collections;import java.util.Arrays;import java.util.ArrayList;import java.io.PrintStream;import java.io.OutputStreamWriter;import java.io.OutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.InputStream;import java.io.FileOutputStream;import java.io.FileInputStream;import java.io.File;import java.io.EOFException;import java.io.BufferedReader;import org.apache.commons.net.ftp.FTPClient;import static cx.ath.matthew.salliere.Gettext._;import cx.ath.matthew.debug.Debug;import com.csvreader.CsvWriter;import com.csvreader.CsvReader;package cx.ath.matthew.salliere; */ * * To Contact me, please email src@matthew.ath.cx * * Boston, MA 02111-1307, USA. * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * copy of the GNU General Public License along with this program; if not, * GNU General Public License for more details. You should have received a * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * the Free Software Foundation. This program is distributed in the hope that * under the terms of the GNU General Public License Version 2 as published by * This program is free software; you can redistribute it and/or modify it * * Copyright (C) 2007 Matthew Johnson * * Salliere Duplicate Bridge Scorer/* adW Ï }j+óåÚÙ¿©£…C&æ È ¬ € Y N ÷ Þ Ö Ñ Ï Î } } } System.exit(1); System.out.println(_("Salliere failed to compute results: ")+e.getMessage()); } Debug.print(Debug.ERR, e); Debug.setThrowableTraces(true); if (Debug.debug) { } catch (Exception e) { writePairs(pairs, new FileOutputStream(args[i+2])); if (modifiedpairs) writeBoards(boards, new FileOutputStream(args[i+1])); if (modifiedboards) out.close(); tabular.close(); } } System.exit(1); syntax(); System.out.println(_("Bad Command: ")+command); else { else if ("scoreteams".equals(command)) teams(boards, tabular, options.get("--teamprefix"), options.get("--teamsize"));ad]¸¡/Ô½kTû µ ž p Y  ø q Z   ² ™ ” “ U P 4  ô Ú ´ š b H ë Ñ « ‘ k Q éÍÅÀpkL%ÞÁ“v<èË©ŒjMгŠm+ͰmPôµ˜|Z;æÀ¤yS7öåº case Hand.AVERAGE_PLUS: switch (b.getEWAverage()) { } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60"); case Hand.AVERAGE_PLUS: switch (b.getNSAverage()) { out.print("A"); if (b.isAveraged()) { out.print('"'); out.print("\t"); out.print(""+b.getEWMP()); // double, recalculated out.print("\t"); out.print(""+b.getNSMP()); // double, recalculated out.print("\t"); out.print("\""+b.getDeclarer()+'"'); // text, not used out.print("\t"); out.print("\""+b.getTricks()+'"'); // text, not used out.print("\t"); out.print('"'+b.getContract()+'"'); // text, not used out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print(""+(int) b.getEWScore()); out.print("\t"); out.print(""+(int) b.getNSScore()); out.print("\t"); out.print(b.getEW()); out.print("\t"); out.print(b.getNS()); out.print("\t"); out.print(b.getNumber()); // int, non zero out.print("\t"); out.print("\"\""); // section, not used == "" out.print("\t"); out.print("\"\""); // spare == "" out.print("\t"); out.print("0"); // spare == 0 out.print("\t"); for (Hand b: bd.getHands()) { for (Board bd: boards) { { private static void doR(PrintStream out, List boards, String session) } } out.print("\r\n"); out.print("\"NS\""); // for a 2 winner movement, set this to the direction they were sitting. out.print("\t"); out.print('"'+names[1]+'"'); out.print("\t"); out.print('"'+names[0]+'"'); out.print("\t"); out.print('"'+names[0]+" & "+names[1]+'"'); String[] names = p.getNames(); out.print("\t"); out.print(p.getNumber()); // pair number (int) out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); for (Pair p: pairs) { { private static void doP(PrintStream out, List pairs) } out.print("\r\n"); out.print('"'+options.get("event")+'"'); // event name, text (max 50 chars) out.print("\t"); out.print('"'+options.get("date")+'"'); // "dd/mm/yyyy" out.print("\t"); out.print('"'+ECATS_PROGRAM_VERSION+'"'); // program version. Important. My program? their program? this number seems to work... out.print("\t"); out.print(options.get("session")); //session #, compulsory, numeric out.print("\t"); out.print("\"false\""); //spare = false out.print("\t"); out.print('"'+options.get("email")+'"'); //email (max 50 chars) out.print("\t"); out.print('"'+options.get("fax")+'"'); //fax (max 50 chars) out.print("\t"); out.print('"'+options.get("phone")+'"'); //phone, compulsory (max 50 chars) out.print("\t"); out.print('"'+options.get("name")+'"'); //name (max 50 chars) out.print("\t"); out.print('"'+options.get("country")+'"'); //country, compulsory, spelling agreed in advance (max 50 chars) out.print("\t"); out.print('"'+options.get("county")+'"'); //county (max 50 chars)ad¼fÚ¾“mQ6ÿñÕ¸€c;ö × Ì Ä ¿ ¾ 0 +  ÿ Ä r q ? ;  É ¥ Ž q ' ÷ ö Ø Ž j T S 8 î Ï ¹ ¸ – j ûóòmhgfé䪩˜qeA Ö zya/ûÍ̪vB!ÿÈ”gfJùÕ¿XW:½£- ï¼» System.err.print(_("Uploading results")); // write boards file System.err.println(); if (!ftp.completePendingCommand()) throw new IOException(_("Uploading pairs failed")); out.close(); doP(out, pairs); out = new PrintStream(ftp.storeFileStream(prefix+"P.txt")); System.err.print(_("Uploading pair details")); // write pairs file if (!ftp.completePendingCommand()) throw new IOException(_("Uploading club details failed")); out.close(); doC(out, boards, options); PrintStream out = new PrintStream(ftp.storeFileStream(prefix+"C.txt")); // write club file String prefix = prefixb.toString(); prefixb.append(phone.replaceAll(" ", "")); prefixb.append(clubName.replaceAll(" ", "")); prefixb.append(session); prefixb.append('0'); for (int i = session.length(); i < 6; i++) StringBuffer prefixb = new StringBuffer(); // calculate file prefix String phone = options.get("phone"); String clubName = options.get("clubName"); String session = options.get("session"); // get options ftp.enterLocalPassiveMode(); ftp.setFileType(FTPClient.BINARY_FILE_TYPE); ftp.changeWorkingDirectory(ECATS_UPLOAD_DIR); ftp.login(ECATS_USERNAME, ECATS_PASSWORD); ftp.connect(ECATS_SERVER); try { FTPClient ftp = new FTPClient(); // connect System.err.println(_("Uploading scores to ECATS")); { public static void uploadToECATS(List boards, List pairs, Map options) throws ScoreException } System.err.println(_("ECATS files have been written. Email the files C.txt, P.txt, R.txt and E.txt to results@simpairs.com")); } throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { out.close(); out.print("End\r\n"); out = new PrintStream(new FileOutputStream(exportdir+"/E.txt")); // write end file out.close(); doR(out, boards, session); out = new PrintStream(new FileOutputStream(exportdir+"/R.txt")); // write boards file out.close(); doP(out, pairs); out = new PrintStream(new FileOutputStream(exportdir+"/P.txt")); // write pairs file out.close(); doC(out, boards, options); PrintStream out = new PrintStream(new FileOutputStream(exportdir+"/C.txt")); // write club file String session = options.get("session"); System.err.println(_("Exporting scores in ECATS format to ")+exportdir); exportdir = new File (".").getCanonicalPath(); if (null == exportdir) try { { public static void exportToECATS(List boards, List pairs, Map options, String exportdir) throws ScoreException } } } out.print("\r\n"); out.print("0"); //spare = 0 out.print("\t"); out.print("0"); //spare = 0 out.print("\t"); out.print(session); // session number again out.print("\t"); out.print('"'); } } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60");adÐi»—bÿ䟀jò ¿ ¨ k ? 0  ø Ô e ] X W å à Ä    e H C B ® © v u 9 8 $  í Á • D < 5 úÅ”dD% Û¨–wH Ð\öîéè˜|cFA@ûöÚǪ¥¤(#ØÉ™j;õêéе—fM/!øÐÏ String[] headers = new String[3]; } themimps += -res[0]; else usimps += res[0]; if (res[0] > 0) double[] res = b.sumimp(prefix, teams); for (Board b: boards) { double themimps = 0; double usimps = 0; } throw new ScoreException(teamsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { teams = Integer.parseInt(teamsize); try { if (null != teamsize && teamsize.length() >= 0) int teams = 4; { public static void teams(List boards, TablePrinter tabular, String prefix, String teamsize) throws ScoreException } modifiedboards = true; b.ximp(); for (Board b: boards) { public static void ximp(List boards) throws ScoreException } modifiedboards = true; b.matchPoint(); for (Board b: boards) { public static void matchpoint(List boards) throws ScoreException } } } new Object[] { boards[i].getNumber(), h.getNS(), h.getEW() })); MessageFormat.format(_("Board {0} was played by {1} and {2}, which I was not expecting."), throw new MovementVerificationException( if (!pairs.contains(h.getNS()+" "+h.getEW())) for (Hand h: boards[i].getHands()) // check the pairs } else { pairs.add(h.getNS()+" "+h.getEW()); for (Hand h: boards[i].getHands()) pairs.clear(); // reset the pairs if (0 == (i % size)) { for (int i = 0; i < boards.length; i++) { Set pairs = new TreeSet(); Board[] boards = boardv.toArray(new Board[0]); Collections.sort(boardv, new BoardNumberComparer()); } throw new MovementVerificationException(setsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { size = Integer.parseInt(setsize); try { int size = 0; if (null == setsize || setsize.length() == 0) return; b.validate(); for (Board b: boardv) { public static void verify(List boardv, String setsize) throws MovementVerificationException, BoardValidationException, HandParseException } modifiedboards = true; h.score(); if (!h.isAveraged()) for (Hand h: b.getHands()) for (Board b: boards) { public static void score(List boards) throws ScoreException, ContractParseException, HandParseException } } throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); } catch (IOException e) {} ftp.disconnect(); ftp.logout(); try { if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { ftp.disconnect(); ftp.logout(); System.err.println(_("Upload complete")); // log out if (!ftp.completePendingCommand()) throw new IOException(_("Uploading end file failed")); out.close(); out.print("End\r\n"); out = new PrintStream(ftp.storeFileStream(prefix+"E.txt")); // write end file if (!ftp.completePendingCommand()) throw new IOException(_("Uploading results failed")); System.err.println(); out.close(); doR(out, boards, session); out = new PrintStream(ftp.storeFileStream(prefix+"R.txt"));ad ®dß¼˜`üϯlLç › š t _ Z Y  ñ Ü ¿ º ¹ w r X > "   Ž ‰ q = . ü Í ž J ? >  Ê • d c + ßÞ©Š\)(õ²«–•o>õ½ˆR˜M7öË™h5« „ƒZB:5ÈÛ†qU?& ýßÀ®­ "" }; : _("MPs:"), ximp ? _("IMPs") "", _("Score:"), _("Tricks"), _("By"), _("Contract"), _("EW"), _("NS"), String[] headers = new String[] { { public static void boardbyboard(List boards, TablePrinter tabular, boolean ximp, boolean withpar) } } tabular.gap(); tabular.print(headers, matrix); start += grouping; } matrix[matrix.length-1][j+1] = format.format(sums[j], tmp, field).toString(); matrix[matrix.length-2][j+1] = " "; StringBuffer tmp = new StringBuffer(); for (int j = 0; j < sums.length; j++) { matrix[matrix.length-1][0] = _("Total"); matrix[matrix.length-2][0] = " "; } } matrix[i][j+1] = " "; } else sums[j] += boards[i+start].getMPs(pairs[j].getNumber()); matrix[i][j+1] = format.format(boards[i+start].getMPs(pairs[j].getNumber()), tmp, field).toString(); if (boards[i+start].played(pairs[j].getNumber())) { StringBuffer tmp = new StringBuffer(); for (int j = 0; j < pairs.length; j++) { matrix[i][0] = boards[i+start].getNumber(); for (int i = 0; i+start < boards.length && i < grouping; i++) { float[] sums = new float[pairs.length]; while (start < boards.length) { int start = 0; String[][] matrix = new String[grouping+2][pairs.length+1]; if (0 == grouping) grouping = boards.length; headers[j+1] = pairs[j].getNumber()+" "; for (int j = 0; j < pairs.length; j++) headers[0] = _("Board"); String[] headers = new String[pairs.length+1]; FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.##"); Pair[] pairs = pairv.toArray(new Pair[0]); Board[] boards = boardv.toArray(new Board[0]); Collections.sort(pairv, new PairNumberComparer()); Collections.sort(boardv, new BoardNumberComparer()); } throw new MovementVerificationException(setsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { grouping = Integer.parseInt(setsize); try { if (null != setsize && setsize.length() >= 0) int grouping = 0; { public static void matrix(List pairv, List boardv, TablePrinter tabular, String setsize) throws MovementVerificationException } modifiedpairs = true; p.total(boards); for (Pair p: pairs) { public static void total(List pairs, List boards) } modifiedboards = true; b.parimp(); for (Board b: boards) { public static void parimp(List boards) throws ScoreException } tabular.gap(); tabular.print(headers, matrix); matrix[0][2] = format.format(usimps-themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][1] = format.format(themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][0] = format.format(usimps, tmp, field).toString(); tmp = new StringBuffer(); String[][] matrix = new String[1][3]; StringBuffer tmp; FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.##"); headers[2] = _("Difference"); headers[1] = _("Them IMPs"); headers[0] = _("Us IMPs");adÝkÅĦlB ëÅU8-¡ “ [   ú õ ‰ „ \ D .  ý ç Î µ ¥ ‡ g . ó ò Ú È ¦ ‹ ƒ j N ,   ö  § ‚ O 5 麣Šs\E.þη mMî×À©’b2ý÷ò·¥¡œ›š$Ú•‰=ìr5*óÇjbF&þÝÜ for (String n: names) { String[] names = p.getNames(); double handicap = 0.0; for (Pair p: pairs) { } throw new ScoreException(_("Failure in reading handicap file: ")+IOe.getMessage()); if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { in.close(); } handicaps.put(values[0], new Double(values[1])); if (values.length != 2) throw new ScoreException(_("Malformed handicap line: ")+Arrays.deepToString(values)); String[] values = in.getValues(); while (in.readRecord()) { CsvReader in = new CsvReader(new InputStreamReader(handicapfile)); try { Map pairhandicaps = new HashMap(); Map handicaps = new HashMap(); { public static Map readHandicapData(List pairs, InputStream handicapfile) throws ScoreException } } tabular.gap(); tabular.print(headers, lines.toArray(new String[0][])); } } } lines.add(line); line[8] = ex[9]; line[7] = ex[6].equals("0") ? "" : ex[6]; line[6] = ex[7].equals("0") ? "" : ex[7]; line[5] = ex[5]; line[4] = ex[4]; line[3] = ex[3]; line[2] = ex[1]; line[1] = _("EW"); line[0] = ex[0]; String[] line = new String[ex.length-1]; String[] ex = h.export(); } else if (h.getEW().equals(p.getNumber())) { lines.add(line); line[8] = ex[8]; line[7] = ex[7].equals("0") ? "" : ex[7]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[5]; line[4] = ex[4]; line[3] = ex[3]; line[2] = ex[2]; line[1] = _("NS"); line[0] = ex[0]; String[] line = new String[ex.length-1]; String[] ex = h.export(); if (h.getNS().equals(p.getNumber())) { for (Hand h: hands) { Collections.sort(hands, new HandNSComparer()); List hands = b.getHands(); for (Board b: boards) { Vector lines = new Vector(); tabular.header(header); } header += ", "+n; for (String n: p.getNames()) { header += p.getNumber(); header = _("Pair "); else header = _("Player "); if (p.getNames().length == 1) String header; for (Pair p: pairs) { Collections.sort(boards, new BoardNumberComparer()); Collections.sort(pairs, new PairNumberComparer()); : _("MPs:")}; ximp ? _("IMPs") "", _("Score:"), _("Tricks"), _("By"), _("Contract"), _("VS"), _("Dir"), _("Board"), String[] headers = new String[] { { public static void scorecards(List pairs, List boards, TablePrinter tabular, boolean ximp) } } tabular.gap(); tabular.print(headers, lines.toArray(new String[0][])); tabular.header(_("Board: ")+b.getNumber()); else tabular.header(_("Board: ")+b.getNumber()+" [ "+b.getParContract()+" by "+b.getPar().getDeclarer()+" ]"); if (withpar) } lines.add(line); System.arraycopy(ex, 1, line, 0, line.length); String[] line = new String[ex.length-1]; String[] ex = h.export(); for (Hand h: hands) { Collections.sort(hands, new HandNSComparer()); List hands = b.getHands(); Vector lines = new Vector(); for (Board b: boards) { Collections.sort(boards, new BoardNumberComparer());adš\ײ—Œ`7/—’÷ Ê Š ‚ f a Ø Ó ¶ y K J , +  ö Ú Ã ¼ ˜ — m * ³ d c .   ƒ Y Á®hóòË|_ í·mEÛx#÷ïÓÎÍ50÷º¹„_?îÌ–yq`?2úÕ´¬š™ if (orange) } headerv.add(_("%age")); headerv.add(_("h'cap")); if (handicaps) headerv.add(_("MPs")); else { headerv.add(_("IMPs")); if (ximp) } headerv.add(""); for (int i = 1; i < Pair.getMaxNames(); i++) headerv.add(_("Names")); headerv.add(_("Pair")); } else { headerv.add(_("Name")); headerv.add(_("Num")); if (Pair.getMaxNames() == 1) { Vector headerv = new Vector(); Collections.sort(pairs, new PairPercentageComparer()); Vector results = new Vector(); { public static void results(List pairs, TablePrinter tabulate, boolean orange, boolean ximp, Map handicapdata, boolean handicaps) } modifiedpairs = true; } } ps[j].setLPs(award); new Object[] { award, ps[j].getNumber(), ps[j].getLPs() })); MessageFormat.format(_("Calculated {0} LPs for pair {1} but data says {2}."), throw new ScoreException( if (ps[j].getLPs() != 0 && ps[j].getLPs() != award) for (int j = a; j <= i; j++) { if (award < scale.getMin() && award > 0) award = scale.getMin(); double award = Math.ceil(total / (1.0+i-a)); total += LPs[++i]; while (i+1 < ps.length && ps[i].getPercentage()==ps[i+1].getPercentage()) int total = LPs[i]; int a = i; for (int i = 0; i < ps.length && i < awarded; i++) { // award LPs, splitting on draws else LPs[i] = (int) Math.ceil(lp); if (lp > scale.getMax(boards.size())) LPs[i] = scale.getMax(boards.size()); for (int i = 0; i < LPs.length && i < awarded; i++, lp -= rate) double lp = top; if (Debug.debug) Debug.print(Debug.DEBUG, "Awarding LPs to "+ps.length+" pairs, top is "+top+" rate is "+rate+" number receiving LPs: "+awarded); double rate = scale.getRate(arity); double top = scale.getTop(npairs, arity, boards.size()); int awarded = scale.numberAwards(npairs, arity, boards.size()); int[] LPs = new int[ps.length]; // calculate LP scale based on number of pairs new Object[] { new Integer(scale.minPairs(arity)) })); MessageFormat.format(_("Must have at least {0} competitors to award local points in this event"), if (ps.length < scale.minPairs(arity)) throw new ScoreException( // check we have enough to give LPs npairs = originaltables * arity; else npairs = ps.length; if (-1 == originaltables) int arity = ps[0].getNames().length; int npairs; if (ps.length == 0) return; Pair[] ps = pairs.toArray(new Pair[0]); Collections.sort(pairs, new PairPercentageComparer()); // sort pairs in order { public static void localpoint(List pairs, List boards, MasterPointScale scale, int originaltables) throws ScoreException } modifiedpairs = true; } p.setPercentage(p.getPercentage()-handicap+normalize); double handicap = handicaps.get(p); for (Pair p: pairs) { if (null == handicaps) throw new ScoreException(_("Must supply a handicap file before calculating handicapped scores")); { public static void handicap(List pairs, Map handicaps, double normalize) throws ScoreException } return pairhandicaps; } pairhandicaps.put(p, handicap); handicap /= (double) names.length; } handicap += v; if (null == v) v = 50.0; Double v = handicaps.get(n);ad'ÇcàÕµ´|{kL'öÉ“wlaDÖ ³ Š Y # æ ” a ` ± r S H G  ñ ì ë » Š ‰ _ Z N 2  é Å ™ Ž U ä¾–põË¢xH﹊X#óÊšŠ]0ÿÍŒZ3긠V:ôÎÔ~bWîÒÇÆ } System.exit(1); ECatsOptionsMap.printOptions(); if (null != options.get("--print-ecats-options")) { } System.exit(1); syntax(); if (null != options.get("--help")) { } commands.add(args[i]); } else } System.exit(1); syntax(); System.out.println(_("Error: unknown option ")+opt[0]); } else { options.put(opt[0], opt[1]); else options.put(opt[0], "true"); if (opt.length == 1) if (options.containsKey(opt[0])) { if (Debug.debug) Debug.print(Arrays.asList(opt)); String[] opt = args[i].split("="); else if (args[i].startsWith("--")) { if ("--".equals(args[i])) break; for (i = 0; i < args.length; i++) { int i; options.put("--original-entry", "-1"); options.put("--mpscale", null); options.put("--print-mpscales", null); options.put("--print-ecats-options", null); options.put("--ecats-export-dir", null); options.put("--ecats-options", null); options.put("--handicap-normalizer", "0.0"); options.put("--handicapdata", null); options.put("--trickdata", null); options.put("--with-handicaps", null); options.put("--with-par", null); options.put("--setsize", null); options.put("--teamprefix", ""); options.put("--teamsize", null); options.put("--title", _("Salliere Duplicate Bridge Scorer: Results")); options.put("--ximp", null); options.put("--orange", null); options.put("--help", null); options.put("--output", "-"); HashMap options = new HashMap(); Vector commands = new Vector(); } Debug.setThrowableTraces(true); Debug.loadConfig(f); if (f.exists()) File f = new File("debug.conf"); if (Debug.debug) { try { { public static void main(String[] args) public static boolean modifiedboards = false; public static boolean modifiedpairs = false; } tabulate.gap(); tabulate.print(header, results.toArray(new String[0][])); } results.set(i, n); System.arraycopy(r, r.length-2, n, r.length-1, 2); if (Debug.debug) Debug.print("Printing handicap "+n[r.length-2]+" for "+p); n[r.length-2] = format.format(handicapdata.get(p), tmp, field).toString(); StringBuffer tmp = new StringBuffer(); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.#"); System.arraycopy(r, 0, n, 0, r.length-2); String[] n = new String[r.length+1]; String[] r = results.get(i); Pair p = pairs.get(i); for (int i = 0; i < pairs.size(); i++) { if (handicaps) results.add(p.export()); for (Pair p: pairs) else } results.add(b); System.arraycopy(a, 5, b, 4, a.length-5); System.arraycopy(a, 0, b, 0, 4); String[] b = new String[a.length-1]; String[] a = p.export(); for (Pair p: pairs) { if (ximp) String[] header = headerv.toArray(new String[0]); headerv.add(_("LPs")); else headerv.add(_("OPs"));adWJÈœ€utPêÎÃÂ¥Š‰KÓ  t s C B ¤ ™ ˜ 7 6   Ð ¶ „ f W   ã ± x F Ý £ Z  Ï–N>ýçËÀ¶lkA °i%eülö@¶{<ÛWV else if ("ecats-export".equals(command)) exportToECATS(boards, pairs, ecatsoptions, options.get("--ecats-export-dir")); else if ("ecats-upload".equals(command)) uploadToECATS(boards, pairs, ecatsoptions); else if ("parimp".equals(command)) parimp(boards); else if ("ximp".equals(command)) ximp(boards); else if ("handicap".equals(command)) handicap(pairs, handicapdata, Double.parseDouble(options.get("--handicap-normalizer"))); else if ("localpoint".equals(command)) localpoint(pairs, boards, MasterPointScale.getScale(options.get("--mpscale")), Integer.parseInt(options.get("--original-entry"))); else if ("scorecards".equals(command)) scorecards(pairs, boards, tabular, null != options.get("--ximp")); else if ("boards".equals(command)) boardbyboard(boards, tabular, null != options.get("--ximp"), null != options.get("--with-par")); else if ("matrix".equals(command)) matrix(pairs, boards, tabular, options.get("--setsize")); else if ("results".equals(command)) results(pairs, tabular, null != options.get("--orange"), null != options.get("--ximp"), handicapdata, null != options.get("--with-handicaps")); else if ("total".equals(command)) total(pairs, boards); else if ("matchpoint".equals(command)) matchpoint(boards); else if ("verify".equals(command)) verify(boards, options.get("--setsize")); if ("score".equals(command)) score(boards); for (String command: commands) { tabular.header(options.get("--title")); tabular.init(); } System.exit(1); syntax(); System.out.println(_("Unknown format: ")+format[0]); else { tabular = new PDFTablePrinter(options.get("--title"), out); else if ("pdf".equals(format[0].toLowerCase())) tabular = new HTMLFragTablePrinter(options.get("--title"), out); else if ("htmlfrag".equals(format[0].toLowerCase())) tabular = new HTMLTablePrinter(options.get("--title"), out); else if ("html".equals(format[0].toLowerCase())) tabular = new CSVTablePrinter(out); else if ("csv".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); else if ("txt".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); if (format.length == 1) out = new PrintStream(new FileOutputStream(format[format.length-1])); else out = System.out; if ("-".equals(format[format.length-1])) PrintStream out; String[] format = options.get("--output").split(":"); TablePrinter tabular = null; Map ecatsoptions = new ECatsOptionsMap(options.get("--ecats-options")); } handicapdata = readHandicapData(pairs, new FileInputStream(options.get("--handicapdata"))); if (null != options.get("--handicapdata")) { Map handicapdata = null; } readTrickData(boards, new FileInputStream(options.get("--trickdata"))); if (null != options.get("--trickdata")) { pairs = readPairs(new FileInputStream(args[i+2]), boards); boards = readBoards(new FileInputStream(args[i+1])); List pairs; List boards; } System.exit(1); syntax(); System.out.println(_("You must specify boards.csv and names.csv")); if (args.length < (i+3)) { } System.exit(1); MasterPointScale.printScales(); if (null != options.get("--print-mpscales")) {ad1Éa㺑ƒZO*äßÞˆƒDØ Ë ¨ z 9  Ý Ò ­ › ™ f E  ð Ç ž s G . é Ð ® § ¡ œ ˜ — ƒ ~ } - ( â È ¢ Š ‰ q l ' ì›=œØÓÒÑ~y3óÊ·²±TO:#ê®—Q:ì«”;$àÉÈ out.print("\t"); out.print('"'+options.get("town")+'"'); //town (max 50 chars) out.print("\t"); out.print('"'+options.get("clubName")+'"'); //club name, compulsory (max 50 chars) out.print("\t"); out.print("\"true\""); // true iff contracts were recorded out.print("\t"); out.print("0"); // #boards/round (not important) out.print("\t"); out.print(""+boards.size()); // # boards played (not important) out.print("\t"); out.print("\"false\""); // true iff 2 winner movement out.print("\t"); out.print("1"); //spare = 1 out.print("\t"); // write C.txt { private static void doC(PrintStream out, List boards, Map options) } out.close(); out.writeRecord(h.export()); for (Hand h: b.getHands()) for (Board b: boards) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writeBoards(List boards, OutputStream os) throws IOException } System.out.println(" Formats: txt html htmlfrag pdf csv"); System.out.println(" Options: --help --output=[:]file --title=title --orange --setsize=N --ximp --with-par --trickdata= --handicapdata= --with-handicaps --handicap-normalizer= --ecats-options= --print-ecats-options --mpscale= --print-mpscales --teamsize=N --teamprefix= --original-entry=<#tables>"); System.out.println(" Commands: verify score matchpoint ximp parimp total handicap localpoint results matrix boards ecats-upload scoreteams scorecards"); System.out.println("Usage: salliere [options] [commands] -- "); System.out.println("Salliere Duplicate Bridge Scorer - version "+version); .getImplementationVersion(); String version = Package.getPackage("cx.ath.matthew.salliere") { static void syntax() } out.close(); out.writeRecord(p.export()); for (Pair p: pairs) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writePairs(List pairs, OutputStream os) throws IOException } return pairs; } } } } pairmap.get(s).addHand(h); for (String s: ss) ss = h.getEW().split("\\."); pairmap.get(s).addHand(h); for (String s: ss) String[] ss = h.getNS().split("\\."); // probably individual } else { pairmap.get(h.getEW()).addHand(h); pairmap.get(h.getNS()).addHand(h); if (pairmap.containsKey(h.getNS())) { System.err.println("NS="+h.getNS()); for (Hand h: b.getHands()) { for (Board b: boards) { if (null != boards) { in.close(); } catch (EOFException EOFe) {} } pairmap.put(p.getNumber(), p); pairs.add(p); Pair p = new Pair(values); if (Debug.debug) Debug.print(Arrays.asList(values)); String[] values = in.getValues(); while (in.readRecord()) { try { HashMap pairmap = new HashMap(); List pairs = new Vector(); CsvReader in = new CsvReader(new InputStreamReader(is)); { static List readPairs(InputStream is, List boards) throws IOException } return new ArrayList(boards.values()); in.close(); } catch (EOFException EOFe) {} } b.addHand(new Hand(values)); } boards.put(values[0], b); b = new Board(values[0]); if (null == b) {ad¨ase`_ôó“B÷ Ö Õ “ Z V < ò Ñ ¦ s /  ã ¹ Y  ÷ ê „ ^ X W B ø å É  l _ %   ÿúùÓ‰$Þ³€<  Á®’H5(îÞÎÈÃÂ7¯ªonû辟—–‘2-~P1ãÕ¨§ Board b = boards.get(values[0]); } Debug.print(in.getCurrentRecord()+": "+Arrays.asList(values)); if (Debug.debug) { String[] values = in.getValues(); while (in.readRecord()) { try { Map boards = new HashMap(); CsvReader in = new CsvReader(new InputStreamReader(is)); { static List readBoards(InputStream is) throws IOException, BoardValidationException } } b.importTricks(s); if (null != (s = br.readLine())) String s; for (Board b: boards) { BufferedReader br = new BufferedReader(new InputStreamReader(trickdatafile)); Collections.sort(boards, new BoardNumberComparer()); { static void readTrickData(List boards, InputStream trickdatafile) throws IOException } } return points2-points1; if (Debug.debug) Debug.print(Debug.DEBUG, ob1.getNumber()+" have "+points1+" points and "+ob2.getNumber()+" have "+points2+" points."); } } points2++; points1++; if (Debug.debug) Debug.print(Debug.VERBOSE, "Draw"); } else { points2 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" win"); } else if (mp1 < mp2) { points1 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" win"); if (mp1 > mp2) { else mp2 = h.getEWMP(); || h.getNS().endsWith("."+ob2.getNumber())) mp2 = h.getNSMP(); || h.getNS().startsWith(ob2.getNumber()+".") if (h.getNS().equals(ob2.getNumber()) mp1 = h.getBoard().getTop() / 2; double mp1 = 0.0, mp2 = 0.0; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" not played, treating as average"); if (Debug.debug) Debug.print(Debug.VERBOSE, "Board: "+h.getNumber()); for (Hand h: hands2map.values()) { } } points2++; points1++; if (Debug.debug) Debug.print(Debug.VERBOSE, "Draw"); } else { points2 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" win"); } else if (mp1 < mp2) { points1 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" win"); if (mp1 > mp2) { } mp2 = h.getBoard().getTop() / 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" not played, treating as average"); } else { else mp2 = h.getEWMP(); || h.getNS().endsWith("."+ob2.getNumber())) mp2 = h.getNSMP(); || h.getNS().startsWith(ob2.getNumber()+".") if (h.getNS().equals(ob2.getNumber()) h = hands2map.remove(h.getNumber()); if (hands2map.containsKey(h.getNumber())) { else mp1 = h.getEWMP(); || h.getNS().endsWith("."+ob1.getNumber())) mp1 = h.getNSMP(); || h.getNS().startsWith(ob1.getNumber()+".") if (h.getNS().equals(ob1.getNumber()) double mp1 = 0.0, mp2 = 0.0; if (Debug.debug) Debug.print(Debug.VERBOSE, "Board: "+h.getNumber()); for (Hand h: hands1) { for (Hand h: hands2) hands2map.put(h.getNumber(), h); HashMap hands2map = new HashMap(); int points1 = 0, points2 = 0; if (Debug.debug) Debug.print(Debug.DEBUG, "Point-a-board count-back:"); and only for two-way ties. Matchpoint the matchpoints for these two pairs */ /* Only using this method here, so only works for all-play-all events without direct matches if (Debug.debug) Debug.print(Debug.INFO, "Splitting tie for "+ob1.getNumber()+" and "+ob2.getNumber()); } return 0; if (Debug.debug) Debug.print(Debug.INFO, "Can't Split tie for "+ob1.getNumber()+" and "+ob2.getNumber()+", because there are no hands");adU}ÿر°} if (hands1.size() == 0 || hands2.size() == 0) { List hands2 = ob2.getHands(); List hands1 = ob1.getHands();salliere-0.10/cx/ath/matthew/salliere/.Salliere.java.swk0000644000175000017500000017000011327150526021625 0ustar mjj29mjj29b0VIM 7.1RÑ\KÀ" (mjj29qadesh~mjj29/scm/salliere/cx/ath/matthew/salliere/Salliere.javautf-8 3210#"! Utp ÿo ap`Ñ$1<V fŽ iôd]rÁf3 b™ aû8\adJoüØÔ®«`Ây,à • H ( % ó ð ì ë Ê É © ‰ ˆ e 4 3   æ É ´ ” s W 5  ü Ù ½ ¡ ˆ j M 3   ð Ö ½ } ] \ F D Ì‘TÙØ˜kcAýõðﮩzrL&Ñ¥‰b65  ÍÈ›“WOJIÔÌ1-œuNM if (hands1.size() == 0 || hands2.size() == 0) { List hands2 = ob2.getHands(); List hands1 = ob1.getHands(); if (ob2.getPercentage() != ob1.getPercentage()) return (int) ((ob2.getPercentage()-ob1.getPercentage())*10000.0); // no need to split tie if (Debug.debug) Debug.print(Debug.VERBOSE, "Comparing "+ob1.getNumber()+"["+ob1.getPercentage()+"] and "+ob2.getNumber()+"["+ob2.getPercentage()+"]"); { public int compare(Pair ob1, Pair ob2) { static class PairPercentageComparer implements Comparator } } return ob1.getNumber().compareTo(ob2.getNumber()); { public int compare(Pair ob1, Pair ob2) { static class PairNumberComparer implements Comparator } } return num1-num2; int num2 = Integer.parseInt(v[0]); v = n[n.length-1].split(";"); n = n2.split(":"); int num1 = Integer.parseInt(v[0]); String[] v = n[n.length-1].split(";"); String[] n = n1.split(":"); String n2 = ob2.getNumber(); String n1 = ob1.getNumber(); { public int compare(Board ob1, Board ob2) { static class BoardNumberComparer implements Comparator } } return n1.compareTo(n2); String n2 = ob2.getNS(); String n1 = ob1.getNS(); { public int compare(Hand ob1, Hand ob2) { static class HandNSComparer implements Comparator public static final String ECATS_PROGRAM_VERSION = "5.6.28"; public static final String ECATS_UPLOAD_DIR = "\\sims"; public static final String ECATS_PASSWORD = "simsuser32"; public static final String ECATS_USERNAME = "simsuser"; public static final String ECATS_SERVER = "sims.ecats.co.uk"; // data gathered from looking at ecats-ftp sessions{public class Salliereimport java.text.MessageFormat;import java.text.FieldPosition;import java.text.DecimalFormat;import java.util.Vector;import java.util.TreeSet;import java.util.Set;import java.util.Map;import java.util.List;import java.util.HashMap;import java.util.Comparator;import java.util.Collections;import java.util.Arrays;import java.util.ArrayList;import java.io.PrintStream;import java.io.OutputStreamWriter;import java.io.OutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.InputStream;import java.io.FileOutputStream;import java.io.FileInputStream;import java.io.File;import java.io.EOFException;import java.io.BufferedReader;import org.apache.commons.net.ftp.FTPClient;import static cx.ath.matthew.salliere.Gettext._;import cx.ath.matthew.debug.Debug;import com.csvreader.CsvWriter;import com.csvreader.CsvReader;package cx.ath.matthew.salliere; */ * * To Contact me, please email src@matthew.ath.cx * * Boston, MA 02111-1307, USA. * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * copy of the GNU General Public License along with this program; if not, * GNU General Public License for more details. You should have received a * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * the Free Software Foundation. This program is distributed in the hope that * under the terms of the GNU General Public License Version 2 as published by * This program is free software; you can redistribute it and/or modify it * * Copyright (C) 2007 Matthew Johnson * * Salliere Duplicate Bridge Scorer/* ad%8ЖM‰A1ð Ú ¾ ³ © _ ^ 4 ü £ \  X ï _ é 3 ©n/ÎJÇ´u\=/$# óíÏp0öÊ£˜A( } } } System.exit(1); System.out.println(_("Salliere failed to compute results: ")+e.getMessage()); } Debug.print(Debug.ERR, e); Debug.setThrowableTraces(true); if (Debug.debug) { } catch (Exception e) { writePairs(pairs, new FileOutputStream(args[i+2])); if (modifiedpairs) writeBoards(boards, new FileOutputStream(args[i+1])); if (modifiedboards) out.close(); tabular.close(); } } System.exit(1); syntax(); System.out.println(_("Bad Command: ")+command); else { else if ("scoreteams".equals(command)) teams(boards, tabular, options.get("--teamprefix"), options.get("--teamsize")); else if ("ecats-export".equals(command)) exportToECATS(boards, pairs, ecatsoptions, options.get("--ecats-export-dir")); else if ("ecats-upload".equals(command)) uploadToECATS(boards, pairs, ecatsoptions); else if ("parimp".equals(command)) parimp(boards); else if ("ximp".equals(command)) ximp(boards); else if ("handicap".equals(command)) handicap(pairs, handicapdata, Double.parseDouble(options.get("--handicap-normalizer"))); else if ("localpoint".equals(command)) localpoint(pairs, boards, MasterPointScale.getScale(options.get("--mpscale")), Integer.parseInt(options.get("--original-entry"))); else if ("scorecards".equals(command)) scorecards(pairs, boards, tabular, null != options.get("--ximp")); else if ("boards".equals(command)) boardbyboard(boards, tabular, null != options.get("--ximp"), null != options.get("--with-par")); else if ("matrix".equals(command)) matrix(pairs, boards, tabular, options.get("--setsize")); else if ("results".equals(command)) results(pairs, tabular, null != options.get("--orange"), null != options.get("--ximp"), handicapdata, null != options.get("--with-handicaps")); else if ("total".equals(command)) total(pairs, boards); else if ("matchpoint".equals(command)) matchpoint(boards); else if ("verify".equals(command)) verify(boards, options.get("--setsize")); if ("score".equals(command)) score(boards); for (String command: commands) { tabular.header(options.get("--title")); tabular.init(); } System.exit(1); syntax(); System.out.println(_("Unknown format: ")+format[0]); else { tabular = new PDFTablePrinter(options.get("--title"), out); else if ("pdf".equals(format[0].toLowerCase())) tabular = new HTMLFragTablePrinter(options.get("--title"), out); else if ("htmlfrag".equals(format[0].toLowerCase())) tabular = new HTMLTablePrinter(options.get("--title"), out); else if ("html".equals(format[0].toLowerCase())) tabular = new CSVTablePrinter(out);adc  $¸¡/Ô½kTû µ ž p Y  ø q Z   ² ™ ” “ U P 4  ô Ú ´ š b H   Í § g M åÉÁ¼lgH!Ú½r8äÇ¥ˆfIü̯†i' ɬiL ð±”xV7 â¼ uO3òá¶Œ case Hand.AVERAGE_PLUS: switch (b.getEWAverage()) { } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60"); case Hand.AVERAGE_PLUS: switch (b.getNSAverage()) { out.print("A"); if (b.isAveraged()) { out.print('"'); out.print("\t"); out.print(""+b.getEWMP()); // double, recalculated out.print("\t"); out.print(""+b.getNSMP()); // double, recalculated out.print("\t"); out.print("\""+b.getDeclarer()+'"'); // text, not used out.print("\t"); out.print("\""+b.getTricks()+'"'); // text, not used out.print("\t"); out.print('"'+b.getContract()+'"'); // text, not used out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print(""+(int) b.getEWScore()); out.print("\t"); out.print(""+(int) b.getNSScore()); out.print("\t"); out.print(b.getEW()); out.print("\t"); out.print(b.getNS()); out.print("\t"); out.print(b.getNumber()); // int, non zero out.print("\t"); out.print("\"\""); // section, not used == "" out.print("\t"); out.print("\"\""); // spare == "" out.print("\t"); out.print("0"); // spare == 0 out.print("\t"); for (Hand b: bd.getHands()) { for (Board bd: boards) { { private static void doR(PrintStream out, List boards, String session) } } out.print("\r\n"); out.print("\"NS\""); // for a 2 winner movement, set this to the direction they were sitting. out.print("\t"); out.print('"'+names[1]+'"'); out.print("\t"); out.print('"'+names[0]+'"'); out.print("\t"); out.print('"'+names[0]+ if (names.length > 1) String[] names = p.getNames(); out.print("\t"); out.print(p.getNumber()); // pair number (int) out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); for (Pair p: pairs) { { private static void doP(PrintStream out, List pairs) } out.print("\r\n"); out.print('"'+options.get("event")+'"'); // event name, text (max 50 chars) out.print("\t"); out.print('"'+options.get("date")+'"'); // "dd/mm/yyyy" out.print("\t"); out.print('"'+ECATS_PROGRAM_VERSION+'"'); // program version. Important. My program? their program? this number seems to work... out.print("\t"); out.print(options.get("session")); //session #, compulsory, numeric out.print("\t"); out.print("\"false\""); //spare = false out.print("\t"); out.print('"'+options.get("email")+'"'); //email (max 50 chars) out.print("\t"); out.print('"'+options.get("fax")+'"'); //fax (max 50 chars) out.print("\t"); out.print('"'+options.get("phone")+'"'); //phone, compulsory (max 50 chars) out.print("\t"); out.print('"'+options.get("name")+'"'); //name (max 50 chars) out.print("\t"); out.print('"'+options.get("country")+'"'); //country, compulsory, spelling agreed in advance (max 50 chars) out.print("\t"); out.print('"'+options.get("county")+'"'); //county (max 50 chars)adGK<ÐǦŒfL& ¤ˆ€{+&à à ™ | N 1 ÷ Ú £ † d G %  Ø » ‹ n E ( æ É ˆ k ( Ì ¯ p S 7  öË¡{_4ò×± uK case Hand.AVERAGE_PLUS: switch (b.getEWAverage()) { } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60"); case Hand.AVERAGE_PLUS: switch (b.getNSAverage()) { out.print("A"); if (b.isAveraged()) { out.print('"'); out.print("\t"); out.print(""+b.getEWMP()); // double, recalculated out.print("\t"); out.print(""+b.getNSMP()); // double, recalculated out.print("\t"); out.print("\""+b.getDeclarer()+'"'); // text, not used out.print("\t"); out.print("\""+b.getTricks()+'"'); // text, not used out.print("\t"); out.print('"'+b.getContract()+'"'); // text, not used out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print(""+(int) b.getEWScore()); out.print("\t"); out.print(""+(int) b.getNSScore()); out.print("\t"); out.print(b.getEW()); out.print("\t"); out.print(b.getNS()); out.print("\t"); out.print(b.getNumber()); // int, non zero out.print("\t"); out.print("\"\""); // section, not used == "" out.print("\t"); out.print("\"\""); // spare == "" out.print("\t"); out.print("0"); // spare == 0 out.print("\t"); for (Hand b: bd.getHands()) { for (Board bd: boards) { { private static void doR(PrintStream out, List boards, String session) } } out.print("\r\n"); out.print("\"NS\""); // for a 2 winner movement, set this to the direction they were sitting. out.print("\t"); out.print('"'+names[1]+'"'); out.print("\t"); out.print('"'+names[0]+'"'); out.print("\t"); out.print('"'+names[0]+'"'); else out.print('"'+names[0]+" & "+names[1]+'"');ad©dâÔ³«ƒb?ã—R2ï Ï Š j   ÷ â Ý Ü • t _ B = < ú õ Û Á ¥   Ÿ  ô À ±  P ! Í Â Á † M  çæ®ba, ߬«x5.òÁx@ Ւк’„yN븈.#ÝŽ¸KF ôØÂ©¨ _("Tricks"), _("By"), _("Contract"), _("EW"), _("NS"), String[] headers = new String[] { { public static void boardbyboard(List boards, TablePrinter tabular, boolean ximp, boolean withpar) } } tabular.gap(); tabular.print(headers, matrix); start += grouping; } matrix[matrix.length-1][j+1] = format.format(sums[j], tmp, field).toString(); matrix[matrix.length-2][j+1] = " "; StringBuffer tmp = new StringBuffer(); for (int j = 0; j < sums.length; j++) { matrix[matrix.length-1][0] = _("Total"); matrix[matrix.length-2][0] = " "; } } matrix[i][j+1] = " "; } else sums[j] += boards[i+start].getMPs(pairs[j].getNumber()); matrix[i][j+1] = format.format(boards[i+start].getMPs(pairs[j].getNumber()), tmp, field).toString(); if (boards[i+start].played(pairs[j].getNumber())) { StringBuffer tmp = new StringBuffer(); for (int j = 0; j < pairs.length; j++) { matrix[i][0] = boards[i+start].getNumber(); for (int i = 0; i+start < boards.length && i < grouping; i++) { float[] sums = new float[pairs.length]; while (start < boards.length) { int start = 0; String[][] matrix = new String[grouping+2][pairs.length+1]; if (0 == grouping) grouping = boards.length; headers[j+1] = pairs[j].getNumber()+" "; for (int j = 0; j < pairs.length; j++) headers[0] = _("Board"); String[] headers = new String[pairs.length+1]; FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.##"); Pair[] pairs = pairv.toArray(new Pair[0]); Board[] boards = boardv.toArray(new Board[0]); Collections.sort(pairv, new PairNumberComparer()); Collections.sort(boardv, new BoardNumberComparer()); } throw new MovementVerificationException(setsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { grouping = Integer.parseInt(setsize); try { if (null != setsize && setsize.length() >= 0) int grouping = 0; { public static void matrix(List pairv, List boardv, TablePrinter tabular, String setsize) throws MovementVerificationException } modifiedpairs = true; p.total(boards); for (Pair p: pairs) { public static void total(List pairs, List boards) } modifiedboards = true; b.parimp(); for (Board b: boards) { public static void parimp(List boards) throws ScoreException } tabular.gap(); tabular.print(headers, matrix); matrix[0][2] = format.format(usimps-themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][1] = format.format(themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][0] = format.format(usimps, tmp, field).toString(); tmp = new StringBuffer(); String[][] matrix = new String[1][3]; StringBuffer tmp; FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.##"); headers[2] = _("Difference"); headers[1] = _("Them IMPs"); headers[0] = _("Us IMPs"); String[] headers = new String[3]; } themimps += -res[0]; else usimps += res[0];adêrç×¹šˆML.ôÊ’sMÝ À µ Ÿ )  ã ¢ Š ‚ }  ô Ó § ‹ s ] H ,  ý ä Ô ¶ – l a E -  û å Ì ³ £ … e 6 2 ù¾½¥“qVN5÷áÜÁrMÔ´…nU>'ùÉ™‚k8éÒ¹¢‹t]-ýæÏ”tE.ÿèÑ¡qZC êé String[] ex = h.export(); } else if (h.getNS().endsWith("."+p.getNumber())) { lines.add(line); line[7] = ex[9]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[7].equals("0") ? "" : ex[7]; line[4] = ex[5]; line[3] = ex[4]; line[2] = ex[3]; line[1] = _("N"); line[0] = ex[0]; String[] line = new String[ex.length-2]; String[] ex = h.export(); } else if (h.getNS().startsWith(p.getNumber()+".")) { lines.add(line); line[8] = ex[9]; line[7] = ex[6].equals("0") ? "" : ex[6]; line[6] = ex[7].equals("0") ? "" : ex[7]; line[5] = ex[5]; line[4] = ex[4]; line[3] = ex[3]; line[2] = ex[1]; line[1] = _("EW"); line[0] = ex[0]; String[] line = new String[ex.length-1]; String[] ex = h.export(); } else if (h.getEW().equals(p.getNumber())) { lines.add(line); line[8] = ex[8]; line[7] = ex[7].equals("0") ? "" : ex[7]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[5]; line[4] = ex[4]; line[3] = ex[3]; line[2] = ex[2]; line[1] = _("NS"); line[0] = ex[0]; String[] line = new String[ex.length-1]; String[] ex = h.export(); if (h.getNS().equals(p.getNumber())) { for (Hand h: hands) { Collections.sort(hands, new HandNSComparer()); List hands = b.getHands(); for (Board b: boards) { Vector lines = new Vector(); tabular.header(header); } header += ", "+n; for (String n: p.getNames()) { header += p.getNumber(); header = _("Pair "); else header = _("Player "); if (p.getNames().length == 1) String header; for (Pair p: pairs) { Collections.sort(boards, new BoardNumberComparer()); Collections.sort(pairs, new PairNumberComparer()); } if (Debug.debug) Debug.print("Individual"); : _("MPs:")}; ximp ? _("IMPs") "", _("Score:"), _("Tricks"), _("By"), _("Contract"), _("Dir"), _("Board"), headers = new String[] { } else { if (Debug.debug) Debug.print("Pairs"); : _("MPs:")}; ximp ? _("IMPs") "", _("Score:"), _("Tricks"), _("By"), _("Contract"), _("VS"), _("Dir"), _("Board"), headers = new String[] { if (pairs.get(0).getNames().length > 1) { if (0 == pairs.size()) return; String[] headers; { public static void scorecards(List pairs, List boards, TablePrinter tabular, boolean ximp) } } tabular.gap(); tabular.print(headers, lines.toArray(new String[0][])); tabular.header(_("Board: ")+b.getNumber()); else tabular.header(_("Board: ")+b.getNumber()+" [ "+b.getParContract()+" by "+b.getPar().getDeclarer()+" ]"); if (withpar) } lines.add(line); System.arraycopy(ex, 1, line, 0, line.length); String[] line = new String[ex.length-1]; String[] ex = h.export(); for (Hand h: hands) { Collections.sort(hands, new HandNSComparer()); List hands = b.getHands(); Vector lines = new Vector(); for (Board b: boards) { Collections.sort(boards, new BoardNumberComparer()); "" }; : _("MPs:"), ximp ? _("IMPs") "", _("Score:"),adÀfѺ¢‹t]-ýæÏ”tE.ÿ è Ñ ¡ q Z C ê » ¤ Œ u ^ G  ç Ð ¹ ² ¬ § l Z V Q P O Ù Ô J > ò Ï ¡ ' êßʨ|ûÛ³’iD)òÉÁ¥ )$¥‰\øójeH Ýܾ½¯ˆlUN*)ÿ¼EöõÀ¿ // calculate LP scale based on number of pairs new Object[] { new Integer(scale.minPairs(arity)) })); MessageFormat.format(_("Must have at least {0} competitors to award local points in this event"), if (ps.length < scale.minPairs(arity)) throw new ScoreException( // check we have enough to give LPs npairs = originaltables * arity; else npairs = ps.length; if (-1 == originaltables) int arity = ps[0].getNames().length; int npairs; if (ps.length == 0) return; Pair[] ps = pairs.toArray(new Pair[0]); Collections.sort(pairs, new PairPercentageComparer()); // sort pairs in order { public static void localpoint(List pairs, List boards, MasterPointScale scale, int originaltables) throws ScoreException } modifiedpairs = true; } p.setPercentage(p.getPercentage()-handicap+normalize); double handicap = handicaps.get(p); for (Pair p: pairs) { if (null == handicaps) throw new ScoreException(_("Must supply a handicap file before calculating handicapped scores")); { public static void handicap(List pairs, Map handicaps, double normalize) throws ScoreException } return pairhandicaps; } pairhandicaps.put(p, handicap); handicap /= (double) names.length; } handicap += v; if (null == v) v = 50.0; Double v = handicaps.get(n); for (String n: names) { String[] names = p.getNames(); double handicap = 0.0; for (Pair p: pairs) { } throw new ScoreException(_("Failure in reading handicap file: ")+IOe.getMessage()); if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { in.close(); } handicaps.put(values[0], new Double(values[1])); if (values.length != 2) throw new ScoreException(_("Malformed handicap line: ")+Arrays.deepToString(values)); String[] values = in.getValues(); while (in.readRecord()) { CsvReader in = new CsvReader(new InputStreamReader(handicapfile)); try { Map pairhandicaps = new HashMap(); Map handicaps = new HashMap(); { public static Map readHandicapData(List pairs, InputStream handicapfile) throws ScoreException } } tabular.gap(); tabular.print(headers, lines.toArray(new String[0][])); } } } lines.add(line); line[7] = ex[9]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[7].equals("0") ? "" : ex[7]; line[4] = ex[5]; line[3] = ex[4]; line[2] = ex[3]; line[1] = _("W"); line[0] = ex[0]; String[] line = new String[ex.length-2]; String[] ex = h.export(); } else if (h.getEW().endsWith("."+p.getNumber())) { lines.add(line); line[7] = ex[9]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[7].equals("0") ? "" : ex[7]; line[4] = ex[5]; line[3] = ex[4]; line[2] = ex[3]; line[1] = _("E"); line[0] = ex[0]; String[] line = new String[ex.length-2]; String[] ex = h.export(); } else if (h.getEW().startsWith(p.getNumber()+".")) { lines.add(line); line[7] = ex[9]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[7].equals("0") ? "" : ex[7]; line[4] = ex[5]; line[3] = ex[4]; line[2] = ex[3]; line[1] = _("S"); line[0] = ex[0]; String[] line = new String[ex.length-2];adžbÚ”U+“€:ë Å Ä b N 1 Þ ¿ ‰ ?  Ö ­ J õ Ô É Á ¥   Ÿ   É Œ ‹ V 1  ðáÀžhKC2ä̧†~lLA! èç׸“b5ÿãØÍ°‹ŠtBöÅRÍÌuÞ¿´³s]XW'öõËÆºž if (Debug.debug) { try { { public static void main(String[] args) public static boolean modifiedboards = false; public static boolean modifiedpairs = false; } tabulate.gap(); tabulate.print(header, results.toArray(new String[0][])); } results.set(i, n); System.arraycopy(r, r.length-2, n, r.length-1, 2); if (Debug.debug) Debug.print("Printing handicap "+n[r.length-2]+" for "+p); n[r.length-2] = format.format(handicapdata.get(p), tmp, field).toString(); StringBuffer tmp = new StringBuffer(); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.#"); System.arraycopy(r, 0, n, 0, r.length-2); String[] n = new String[r.length+1]; String[] r = results.get(i); Pair p = pairs.get(i); for (int i = 0; i < pairs.size(); i++) { if (handicaps) results.add(p.export()); for (Pair p: pairs) else } results.add(b); System.arraycopy(a, 5, b, 4, a.length-5); System.arraycopy(a, 0, b, 0, 4); String[] b = new String[a.length-1]; String[] a = p.export(); for (Pair p: pairs) { if (ximp) String[] header = headerv.toArray(new String[0]); headerv.add(_("LPs")); else headerv.add(_("OPs")); if (orange) } headerv.add(_("%age")); headerv.add(_("h'cap")); if (handicaps) headerv.add(_("MPs")); else { headerv.add(_("IMPs")); if (ximp) } headerv.add(""); for (int i = 1; i < Pair.getMaxNames(); i++) headerv.add(_("Names")); headerv.add(_("Pair")); } else { headerv.add(_("Name")); headerv.add(_("Num")); if (Pair.getMaxNames() == 1) { Vector headerv = new Vector(); Collections.sort(pairs, new PairPercentageComparer()); Vector results = new Vector(); { public static void results(List pairs, TablePrinter tabulate, boolean orange, boolean ximp, Map handicapdata, boolean handicaps) } modifiedpairs = true; } } ps[j].setLPs(award); new Object[] { award, ps[j].getNumber(), ps[j].getLPs() })); MessageFormat.format(_("Calculated {0} LPs for pair {1} but data says {2}."), throw new ScoreException( if (ps[j].getLPs() != 0 && ps[j].getLPs() != award) for (int j = a; j <= i; j++) { if (award < scale.getMin() && award > 0) award = scale.getMin(); double award = Math.ceil(total / (1.0+i-a)); total += LPs[++i]; while (i+1 < ps.length && ps[i].getPercentage()==ps[i+1].getPercentage()) int total = LPs[i]; int a = i; for (int i = 0; i < ps.length && i < awarded; i++) { // award LPs, splitting on draws else LPs[i] = (int) Math.ceil(lp); if (lp > scale.getMax(boards.size())) LPs[i] = scale.getMax(boards.size()); for (int i = 0; i < LPs.length && i < awarded; i++, lp -= rate) double lp = top; if (Debug.debug) Debug.print(Debug.DEBUG, "Awarding LPs to "+ps.length+" pairs, top is "+top+" rate is "+rate+" number receiving LPs: "+awarded); double rate = scale.getRate(arity); double top = scale.getTop(npairs, arity, boards.size()); int awarded = scale.numberAwards(npairs, arity, boards.size()); int[] LPs = new int[ps.length];ad ¢aÓ·“g\#Ù²Œd>í à ™ p F  ë ½ ‡ X & ñ Á ˜ h X + þ Í › Z (  Ï ¸ † n $  æÕœ‘bL0%è¼ •]1  å•cXW:àœ›h Ø×¡9.-ÌË¥¤eKûìš™xF Û¢¡ else if ("csv".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); else if ("txt".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); if (format.length == 1) out = new PrintStream(new FileOutputStream(format[format.length-1])); else out = System.out; if ("-".equals(format[format.length-1])) PrintStream out; String[] format = options.get("--output").split(":"); TablePrinter tabular = null; Map ecatsoptions = new ECatsOptionsMap(options.get("--ecats-options")); } handicapdata = readHandicapData(pairs, new FileInputStream(options.get("--handicapdata"))); if (null != options.get("--handicapdata")) { Map handicapdata = null; } readTrickData(boards, new FileInputStream(options.get("--trickdata"))); if (null != options.get("--trickdata")) { pairs = readPairs(new FileInputStream(args[i+2]), boards); boards = readBoards(new FileInputStream(args[i+1])); List pairs; List boards; } System.exit(1); syntax(); System.out.println(_("You must specify boards.csv and names.csv")); if (args.length < (i+3)) { } System.exit(1); MasterPointScale.printScales(); if (null != options.get("--print-mpscales")) { } System.exit(1); ECatsOptionsMap.printOptions(); if (null != options.get("--print-ecats-options")) { } System.exit(1); syntax(); if (null != options.get("--help")) { } commands.add(args[i]); } else } System.exit(1); syntax(); System.out.println(_("Error: unknown option ")+opt[0]); } else { options.put(opt[0], opt[1]); else options.put(opt[0], "true"); if (opt.length == 1) if (options.containsKey(opt[0])) { if (Debug.debug) Debug.print(Arrays.asList(opt)); String[] opt = args[i].split("="); else if (args[i].startsWith("--")) { if ("--".equals(args[i])) break; for (i = 0; i < args.length; i++) { int i; options.put("--original-entry", "-1"); options.put("--mpscale", null); options.put("--print-mpscales", null); options.put("--print-ecats-options", null); options.put("--ecats-export-dir", null); options.put("--ecats-options", null); options.put("--handicap-normalizer", "0.0"); options.put("--handicapdata", null); options.put("--trickdata", null); options.put("--with-handicaps", null); options.put("--with-par", null); options.put("--setsize", null); options.put("--teamprefix", ""); options.put("--teamsize", null); options.put("--title", _("Salliere Duplicate Bridge Scorer: Results")); options.put("--ximp", null); options.put("--orange", null); options.put("--help", null); options.put("--output", "-"); HashMap options = new HashMap(); Vector commands = new Vector(); } Debug.setThrowableTraces(true); Debug.loadConfig(f); if (f.exists()) File f = new File("debug.conf");adÌi»—bÿ䟀jò ¿ ¨ k ? 0  ø Ô e ] X W å à Ä    e H C B ® © v u 9 8 $  í Á • D < 5 úÅ”dD% Û¨–wH Ð\öîé蘆hC!âÅÀ¿zuYF)$#§¢WHéºtihO4åÌË if (res[0] > 0) double[] res = b.sumimp(prefix, teams); for (Board b: boards) { double themimps = 0; double usimps = 0; } throw new ScoreException(teamsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { teams = Integer.parseInt(teamsize); try { if (null != teamsize && teamsize.length() >= 0) int teams = 4; { public static void teams(List boards, TablePrinter tabular, String prefix, String teamsize) throws ScoreException } modifiedboards = true; b.ximp(); for (Board b: boards) { public static void ximp(List boards) throws ScoreException } modifiedboards = true; b.matchPoint(played); for (Board b: boards) } played = b.getHands().size(); if (b.getHands().size() > played) for (Board b: boards) { int played = 0; { public static void matchpoint(List boards) throws ScoreException } } } new Object[] { boards[i].getNumber(), h.getNS(), h.getEW() })); MessageFormat.format(_("Board {0} was played by {1} and {2}, which I was not expecting."), throw new MovementVerificationException( if (!pairs.contains(h.getNS()+" "+h.getEW())) for (Hand h: boards[i].getHands()) // check the pairs } else { pairs.add(h.getNS()+" "+h.getEW()); for (Hand h: boards[i].getHands()) pairs.clear(); // reset the pairs if (0 == (i % size)) { for (int i = 0; i < boards.length; i++) { Set pairs = new TreeSet(); Board[] boards = boardv.toArray(new Board[0]); Collections.sort(boardv, new BoardNumberComparer()); } throw new MovementVerificationException(setsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { size = Integer.parseInt(setsize); try { int size = 0; if (null == setsize || setsize.length() == 0) return; b.validate(); for (Board b: boardv) { public static void verify(List boardv, String setsize) throws MovementVerificationException, BoardValidationException, HandParseException } modifiedboards = true; h.score(); if (!h.isAveraged()) for (Hand h: b.getHands()) for (Board b: boards) { public static void score(List boards) throws ScoreException, ContractParseException, HandParseException } } throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); } catch (IOException e) {} ftp.disconnect(); ftp.logout(); try { if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { ftp.disconnect(); ftp.logout(); System.err.println(_("Upload complete")); // log out if (!ftp.completePendingCommand()) throw new IOException(_("Uploading end file failed")); out.close(); out.print("End\r\n"); out = new PrintStream(ftp.storeFileStream(prefix+"E.txt")); // write end file if (!ftp.completePendingCommand()) throw new IOException(_("Uploading results failed")); System.err.println(); out.close(); doR(out, boards, session); out = new PrintStream(ftp.storeFileStream(prefix+"R.txt"));ad¨ase`_ôó“B÷ Ö Õ “ Z V < ò Ñ ¦ s /  ã ¹ Y  ÷ ê „ ^ X W B ø å É  l _ %   ÿúùÓ‰$Þ³€<  Á®’H5(îÞÎÈÃÂ7¯ªonû辟—–‘2-~P1ãÕ¨§ Board b = boards.get(values[0]); } Debug.print(in.getCurrentRecord()+": "+Arrays.asList(values)); if (Debug.debug) { String[] values = in.getValues(); while (in.readRecord()) { try { Map boards = new HashMap(); CsvReader in = new CsvReader(new InputStreamReader(is)); { static List readBoards(InputStream is) throws IOException, BoardValidationException } } b.importTricks(s); if (null != (s = br.readLine())) String s; for (Board b: boards) { BufferedReader br = new BufferedReader(new InputStreamReader(trickdatafile)); Collections.sort(boards, new BoardNumberComparer()); { static void readTrickData(List boards, InputStream trickdatafile) throws IOException } } return points2-points1; if (Debug.debug) Debug.print(Debug.DEBUG, ob1.getNumber()+" have "+points1+" points and "+ob2.getNumber()+" have "+points2+" points."); } } points2++; points1++; if (Debug.debug) Debug.print(Debug.VERBOSE, "Draw"); } else { points2 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" win"); } else if (mp1 < mp2) { points1 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" win"); if (mp1 > mp2) { else mp2 = h.getEWMP(); || h.getNS().endsWith("."+ob2.getNumber())) mp2 = h.getNSMP(); || h.getNS().startsWith(ob2.getNumber()+".") if (h.getNS().equals(ob2.getNumber()) mp1 = h.getBoard().getTop() / 2; double mp1 = 0.0, mp2 = 0.0; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" not played, treating as average"); if (Debug.debug) Debug.print(Debug.VERBOSE, "Board: "+h.getNumber()); for (Hand h: hands2map.values()) { } } points2++; points1++; if (Debug.debug) Debug.print(Debug.VERBOSE, "Draw"); } else { points2 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" win"); } else if (mp1 < mp2) { points1 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" win"); if (mp1 > mp2) { } mp2 = h.getBoard().getTop() / 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" not played, treating as average"); } else { else mp2 = h.getEWMP(); || h.getNS().endsWith("."+ob2.getNumber())) mp2 = h.getNSMP(); || h.getNS().startsWith(ob2.getNumber()+".") if (h.getNS().equals(ob2.getNumber()) h = hands2map.remove(h.getNumber()); if (hands2map.containsKey(h.getNumber())) { else mp1 = h.getEWMP(); || h.getNS().endsWith("."+ob1.getNumber())) mp1 = h.getNSMP(); || h.getNS().startsWith(ob1.getNumber()+".") if (h.getNS().equals(ob1.getNumber()) double mp1 = 0.0, mp2 = 0.0; if (Debug.debug) Debug.print(Debug.VERBOSE, "Board: "+h.getNumber()); for (Hand h: hands1) { for (Hand h: hands2) hands2map.put(h.getNumber(), h); HashMap hands2map = new HashMap(); int points1 = 0, points2 = 0; if (Debug.debug) Debug.print(Debug.DEBUG, "Point-a-board count-back:"); and only for two-way ties. Matchpoint the matchpoints for these two pairs */ /* Only using this method here, so only works for all-play-all events without direct matches if (Debug.debug) Debug.print(Debug.INFO, "Splitting tie for "+ob1.getNumber()+" and "+ob2.getNumber()); } return 0; if (Debug.debug) Debug.print(Debug.INFO, "Can't Split tie for "+ob1.getNumber()+" and "+ob2.getNumber()+", because there are no hands");ad¼fÚ¾“mQ6ÿñÕ¸€c;ö × Ì Ä ¿ ¾ 0 +  ÿ Ä r q ? ;  É ¥ Ž q ' ÷ ö Ø Ž j T S 8 î Ï ¹ ¸ – j ûóòmhgfé䪩˜qeA Ö zya/ûÍ̪vB!ÿÈ”gfJùÕ¿XW:½£- ï¼» System.err.print(_("Uploading results")); // write boards file System.err.println(); if (!ftp.completePendingCommand()) throw new IOException(_("Uploading pairs failed")); out.close(); doP(out, pairs); out = new PrintStream(ftp.storeFileStream(prefix+"P.txt")); System.err.print(_("Uploading pair details")); // write pairs file if (!ftp.completePendingCommand()) throw new IOException(_("Uploading club details failed")); out.close(); doC(out, boards, options); PrintStream out = new PrintStream(ftp.storeFileStream(prefix+"C.txt")); // write club file String prefix = prefixb.toString(); prefixb.append(phone.replaceAll(" ", "")); prefixb.append(clubName.replaceAll(" ", "")); prefixb.append(session); prefixb.append('0'); for (int i = session.length(); i < 6; i++) StringBuffer prefixb = new StringBuffer(); // calculate file prefix String phone = options.get("phone"); String clubName = options.get("clubName"); String session = options.get("session"); // get options ftp.enterLocalPassiveMode(); ftp.setFileType(FTPClient.BINARY_FILE_TYPE); ftp.changeWorkingDirectory(ECATS_UPLOAD_DIR); ftp.login(ECATS_USERNAME, ECATS_PASSWORD); ftp.connect(ECATS_SERVER); try { FTPClient ftp = new FTPClient(); // connect System.err.println(_("Uploading scores to ECATS")); { public static void uploadToECATS(List boards, List pairs, Map options) throws ScoreException } System.err.println(_("ECATS files have been written. Email the files C.txt, P.txt, R.txt and E.txt to results@simpairs.com")); } throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { out.close(); out.print("End\r\n"); out = new PrintStream(new FileOutputStream(exportdir+"/E.txt")); // write end file out.close(); doR(out, boards, session); out = new PrintStream(new FileOutputStream(exportdir+"/R.txt")); // write boards file out.close(); doP(out, pairs); out = new PrintStream(new FileOutputStream(exportdir+"/P.txt")); // write pairs file out.close(); doC(out, boards, options); PrintStream out = new PrintStream(new FileOutputStream(exportdir+"/C.txt")); // write club file String session = options.get("session"); System.err.println(_("Exporting scores in ECATS format to ")+exportdir); exportdir = new File (".").getCanonicalPath(); if (null == exportdir) try { { public static void exportToECATS(List boards, List pairs, Map options, String exportdir) throws ScoreException } } } out.print("\r\n"); out.print("0"); //spare = 0 out.print("\t"); out.print("0"); //spare = 0 out.print("\t"); out.print(session); // session number again out.print("\t"); out.print('"'); } } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60");ad•`㺑ƒZO*äßÞˆƒDØ Ë ¨ z 9  Ý Ò ­ › ™ f E  ñ È º q <  ÷    ™ “ Ž Š ‰ u p o   Ô º ” | { c ^  Þ/礟žJEÿã¿–ƒ~} ïͶzcϸw`𬕠out.print("\t"); out.print('"'+options.get("town")+'"'); //town (max 50 chars) out.print("\t"); out.print('"'+options.get("clubName")+'"'); //club name, compulsory (max 50 chars) out.print("\t"); out.print("\"true\""); // true iff contracts were recorded out.print("\t"); out.print("0"); // #boards/round (not important) out.print("\t"); out.print(""+boards.size()); // # boards played (not important) out.print("\t"); out.print("\"false\""); // true iff 2 winner movement out.print("\t"); out.print("1"); //spare = 1 out.print("\t"); // write C.txt { private static void doC(PrintStream out, List boards, Map options) } out.close(); out.writeRecord(h.export()); for (Hand h: b.getHands()) for (Board b: boards) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writeBoards(List boards, OutputStream os) throws IOException } System.out.println(" Formats: txt html htmlfrag pdf csv"); System.out.println(" Options: --help --output=[:]file --title=title --orange --setsize=N --ximp --with-par --trickdata= --handicapdata= --with-handicaps --handicap-normalizer= --ecats-options= --print-ecats-options --ecats-export-dir= --mpscale= --print-mpscales --teamsize=N --teamprefix= --original-entry=<#tables>"); System.out.println(" Commands: verify score matchpoint ximp parimp total handicap localpoint results matrix boards ecats-upload ecats-export scoreteams scorecards"); System.out.println("Usage: salliere [options] [commands] -- "); System.out.println("Salliere Duplicate Bridge Scorer - version "+version); .getImplementationVersion(); String version = Package.getPackage("cx.ath.matthew.salliere") { static void syntax() } out.close(); out.writeRecord(p.export()); for (Pair p: pairs) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writePairs(List pairs, OutputStream os) throws IOException } return pairs; } } } } pairmap.get(s).addHand(h); for (String s: ss) if (pairmap.containsKey(s)) ss = h.getEW().split("\\."); pairmap.get(s).addHand(h); for (String s: ss) if (pairmap.containsKey(s)) String[] ss = h.getNS().split("\\."); // probably individual } else { pairmap.get(h.getEW()).addHand(h); pairmap.get(h.getNS()).addHand(h); if (pairmap.containsKey(h.getNS())) { for (Hand h: b.getHands()) { for (Board b: boards) { if (null != boards) { in.close(); } catch (EOFException EOFe) {} } pairmap.put(p.getNumber(), p); pairs.add(p); Pair p = new Pair(values); if (Debug.debug) Debug.print(Arrays.asList(values)); String[] values = in.getValues(); while (in.readRecord()) { try { HashMap pairmap = new HashMap(); List pairs = new Vector(); CsvReader in = new CsvReader(new InputStreamReader(is)); { static List readPairs(InputStream is, List boards) throws IOException } return new ArrayList(boards.values()); in.close(); } catch (EOFException EOFe) {} } b.addHand(new Hand(values)); } boards.put(values[0], b); b = new Board(values[0]); if (null == b) {salliere-0.10/cx/ath/matthew/salliere/.Salliere.java.swj0000644000175000017500000017000011327150630021620 0ustar mjj29mjj29b0VIM 7.1“Ñ\KÓ" Â(mjj29qadesh~mjj29/scm/salliere/cx/ath/matthew/salliere/Salliere.javautf-8 3210#"! Utp ÿo ap`Ñ)18[ f iõc^sÁe4 _™ dø;\adJoüØÔ®«`Ây,à • H ( % ó ð ì ë Ê É © ‰ ˆ e 4 3   æ É ´ ” s W 5  ü Ù ½ ¡ ˆ j M 3   ð Ö ½ } ] \ F D Ì‘TÙØ˜kcAýõðﮩzrL&Ñ¥‰b65  ÍÈ›“WOJIÔÌ1-œuNM if (hands1.size() == 0 || hands2.size() == 0) { List hands2 = ob2.getHands(); List hands1 = ob1.getHands(); if (ob2.getPercentage() != ob1.getPercentage()) return (int) ((ob2.getPercentage()-ob1.getPercentage())*10000.0); // no need to split tie if (Debug.debug) Debug.print(Debug.VERBOSE, "Comparing "+ob1.getNumber()+"["+ob1.getPercentage()+"] and "+ob2.getNumber()+"["+ob2.getPercentage()+"]"); { public int compare(Pair ob1, Pair ob2) { static class PairPercentageComparer implements Comparator } } return ob1.getNumber().compareTo(ob2.getNumber()); { public int compare(Pair ob1, Pair ob2) { static class PairNumberComparer implements Comparator } } return num1-num2; int num2 = Integer.parseInt(v[0]); v = n[n.length-1].split(";"); n = n2.split(":"); int num1 = Integer.parseInt(v[0]); String[] v = n[n.length-1].split(";"); String[] n = n1.split(":"); String n2 = ob2.getNumber(); String n1 = ob1.getNumber(); { public int compare(Board ob1, Board ob2) { static class BoardNumberComparer implements Comparator } } return n1.compareTo(n2); String n2 = ob2.getNS(); String n1 = ob1.getNS(); { public int compare(Hand ob1, Hand ob2) { static class HandNSComparer implements Comparator public static final String ECATS_PROGRAM_VERSION = "5.6.28"; public static final String ECATS_UPLOAD_DIR = "\\sims"; public static final String ECATS_PASSWORD = "simsuser32"; public static final String ECATS_USERNAME = "simsuser"; public static final String ECATS_SERVER = "sims.ecats.co.uk"; // data gathered from looking at ecats-ftp sessions{public class Salliereimport java.text.MessageFormat;import java.text.FieldPosition;import java.text.DecimalFormat;import java.util.Vector;import java.util.TreeSet;import java.util.Set;import java.util.Map;import java.util.List;import java.util.HashMap;import java.util.Comparator;import java.util.Collections;import java.util.Arrays;import java.util.ArrayList;import java.io.PrintStream;import java.io.OutputStreamWriter;import java.io.OutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.InputStream;import java.io.FileOutputStream;import java.io.FileInputStream;import java.io.File;import java.io.EOFException;import java.io.BufferedReader;import org.apache.commons.net.ftp.FTPClient;import static cx.ath.matthew.salliere.Gettext._;import cx.ath.matthew.debug.Debug;import com.csvreader.CsvWriter;import com.csvreader.CsvReader;package cx.ath.matthew.salliere; */ * * To Contact me, please email src@matthew.ath.cx * * Boston, MA 02111-1307, USA. * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * copy of the GNU General Public License along with this program; if not, * GNU General Public License for more details. You should have received a * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * the Free Software Foundation. This program is distributed in the hope that * under the terms of the GNU General Public License Version 2 as published by * This program is free software; you can redistribute it and/or modify it * * Copyright (C) 2007 Matthew Johnson * * Salliere Duplicate Bridge Scorer/* aduu;Ç•\,ò©kå L 6    ì » º X ÿ ¸ t ´ K » E Ê‹*¦#Ѹ™‹€eOI+éÌŒnR&ÿô„|wut} } } System.exit(1); System.out.println(_("Salliere failed to compute results: ")+e.getMessage()); } Debug.print(Debug.ERR, e); Debug.setThrowableTraces(true); if (Debug.debug) { } catch (Exception e) { writePairs(pairs, new FileOutputStream(args[i+2])); if (modifiedpairs) writeBoards(boards, new FileOutputStream(args[i+1])); if (modifiedboards) out.close(); tabular.close(); } } System.exit(1); syntax(); System.out.println(_("Bad Command: ")+command); else { else if ("scoreteams".equals(command)) teams(boards, tabular, options.get("--teamprefix"), options.get("--teamsize")); else if ("ecats-export".equals(command)) exportToECATS(boards, pairs, ecatsoptions, options.get("--ecats-export-dir")); else if ("ecats-upload".equals(command)) uploadToECATS(boards, pairs, ecatsoptions); else if ("parimp".equals(command)) parimp(boards); else if ("ximp".equals(command)) ximp(boards); else if ("handicap".equals(command)) handicap(pairs, handicapdata, Double.parseDouble(options.get("--handicap-normalizer"))); else if ("localpoint".equals(command)) localpoint(pairs, boards, MasterPointScale.getScale(options.get("--mpscale")), Integer.parseInt(options.get("--original-entry"))); else if ("scorecards".equals(command)) scorecards(pairs, boards, tabular, null != options.get("--ximp")); else if ("boards".equals(command)) boardbyboard(boards, tabular, null != options.get("--ximp"), null != options.get("--with-par")); else if ("matrix".equals(command)) matrix(pairs, boards, tabular, options.get("--setsize")); else if ("results".equals(command)) results(pairs, tabular, null != options.get("--orange"), null != options.get("--ximp"), handicapdata, null != options.get("--with-handicaps")); else if ("total".equals(command)) total(pairs, boards); else if ("matchpoint".equals(command)) matchpoint(boards); else if ("verify".equals(command)) verify(boards, options.get("--setsize")); if ("score".equals(command)) score(boards); for (String command: commands) { tabular.header(options.get("--title")); tabular.init(); } System.exit(1); syntax(); System.out.println(_("Unknown format: ")+format[0]); else { tabular = new PDFTablePrinter(options.get("--title"), out); else if ("pdf".equals(format[0].toLowerCase())) tabular = new HTMLFragTablePrinter(options.get("--title"), out); else if ("htmlfrag".equals(format[0].toLowerCase())) tabular = new HTMLTablePrinter(options.get("--title"), out); else if ("html".equals(format[0].toLowerCase())) tabular = new CSVTablePrinter(out); else if ("csv".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); else if ("txt".equals(format[0].toLowerCase()))ad8æÍ¬¤Œr îæá‘ŒmF)ÿ â ´ — ] @ ì Ê ­ ‹ n > ! ñ Ô « Ž L / î Ñ Ž q 2  Ö ¹ { \ 1  áÅštX= } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60"); case Hand.AVERAGE_PLUS: switch (b.getNSAverage()) { out.print("A"); if (b.isAveraged()) { out.print('"'); out.print("\t"); out.print(""+b.getEWMP()); // double, recalculated out.print("\t"); out.print(""+b.getNSMP()); // double, recalculated out.print("\t"); out.print("\""+b.getDeclarer()+'"'); // text, not used out.print("\t"); out.print("\""+b.getTricks()+'"'); // text, not used out.print("\t"); out.print('"'+b.getContract()+'"'); // text, not used out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print(""+(int) b.getEWScore()); out.print("\t"); out.print(""+(int) b.getNSScore()); out.print("\t"); out.print(b.getEW()); out.print("\t"); out.print(b.getNS()); out.print("\t"); out.print(b.getNumber()); // int, non zero out.print("\t"); out.print("\"\""); // section, not used == "" out.print("\t"); out.print("\"\""); // spare == "" out.print("\t"); out.print("0"); // spare == 0 out.print("\t"); for (Hand b: bd.getHands()) { for (Board bd: boards) { { private static void doR(PrintStream out, List boards, String session) } } out.print("\r\n"); out.print("\"NS\""); // for a 2 winner movement, set this to the direction they were sitting. out.print("\t"); out.print('"'+'"'); else out.print('"'+names[1]+'"'); if (names.length > 1) out.print("\t");adµm )¸¡/Ô½kTû µ ž p Y  ø q Z   ² ™ ” “ U P 4  ô Ú ´ š b H  × Î ­ “ m T -  «‡‚2-çÊ ƒU8þáªkN,ßÂ’uL/íÐr/Ó¶wZ>ýÒ¨‚f;ùÞ¸§¦ } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60"); case Hand.AVERAGE_PLUS: switch (b.getNSAverage()) { out.print("A"); if (b.isAveraged()) { out.print('"'); out.print("\t"); out.print(""+b.getEWMP()); // double, recalculated out.print("\t"); out.print(""+b.getNSMP()); // double, recalculated out.print("\t"); out.print("\""+b.getDeclarer()+'"'); // text, not used out.print("\t"); out.print("\""+b.getTricks()+'"'); // text, not used out.print("\t"); out.print('"'+b.getContract()+'"'); // text, not used out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print(""+(int) b.getEWScore()); out.print("\t"); out.print(""+(int) b.getNSScore()); out.print("\t"); out.print(b.getEW()); out.print("\t"); out.print(b.getNS()); out.print("\t"); out.print(b.getNumber()); // int, non zero out.print("\t"); out.print("\"\""); // section, not used == "" out.print("\t"); out.print("\"\""); // spare == "" out.print("\t"); out.print("0"); // spare == 0 out.print("\t"); for (Hand b: bd.getHands()) { for (Board bd: boards) { { private static void doR(PrintStream out, List boards, String session) } } out.print("\r\n"); out.print("\"NS\""); // for a 2 winner movement, set this to the direction they were sitting. out.print("\t"); out.print('"'+names[1]+'"'); if (names.length > 1) out.print('"'+names[0]+'"'); out.print("\t"); out.print('"'+names[0]+'"'); else out.print('"'+names[0]+" & "+names[1]+'"'); if (names.length > 1) String[] names = p.getNames(); out.print("\t"); out.print(p.getNumber()); // pair number (int) out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); for (Pair p: pairs) { { private static void doP(PrintStream out, List pairs) } out.print("\r\n"); out.print('"'+options.get("event")+'"'); // event name, text (max 50 chars) out.print("\t"); out.print('"'+options.get("date")+'"'); // "dd/mm/yyyy" out.print("\t"); out.print('"'+ECATS_PROGRAM_VERSION+'"'); // program version. Important. My program? their program? this number seems to work... out.print("\t"); out.print(options.get("session")); //session #, compulsory, numeric out.print("\t"); out.print("\"false\""); //spare = false out.print("\t"); out.print('"'+options.get("email")+'"'); //email (max 50 chars) out.print("\t"); out.print('"'+options.get("fax")+'"'); //fax (max 50 chars) out.print("\t"); out.print('"'+options.get("phone")+'"'); //phone, compulsory (max 50 chars) out.print("\t"); out.print('"'+options.get("name")+'"'); //name (max 50 chars) out.print("\t"); out.print('"'+options.get("country")+'"'); //country, compulsory, spelling agreed in advance (max 50 chars) out.print("\t"); out.print('"'+options.get("county")+'"'); //county (max 50 chars)ad ªc϶˜Šia9õÑ™M5è ¥ … @ Ô Ó ­ ˜ “ ’ K F *  ø ó ò ° « ‘ w [ V U Ç Â ª v g 5  × ƒ x w <  ΜdâÕba.ëäÏΨw.öÁ‹HцpH:/Ò¡n>äÙ½¼“{snüÔ¿ª© _("EW"), _("NS"), String[] headers = new String[] { { public static void boardbyboard(List boards, TablePrinter tabular, boolean ximp, boolean withpar) } } tabular.gap(); tabular.print(headers, matrix); start += grouping; } matrix[matrix.length-1][j+1] = format.format(sums[j], tmp, field).toString(); matrix[matrix.length-2][j+1] = " "; StringBuffer tmp = new StringBuffer(); for (int j = 0; j < sums.length; j++) { matrix[matrix.length-1][0] = _("Total"); matrix[matrix.length-2][0] = " "; } } matrix[i][j+1] = " "; } else sums[j] += boards[i+start].getMPs(pairs[j].getNumber()); matrix[i][j+1] = format.format(boards[i+start].getMPs(pairs[j].getNumber()), tmp, field).toString(); if (boards[i+start].played(pairs[j].getNumber())) { StringBuffer tmp = new StringBuffer(); for (int j = 0; j < pairs.length; j++) { matrix[i][0] = boards[i+start].getNumber(); for (int i = 0; i+start < boards.length && i < grouping; i++) { float[] sums = new float[pairs.length]; while (start < boards.length) { int start = 0; String[][] matrix = new String[grouping+2][pairs.length+1]; if (0 == grouping) grouping = boards.length; headers[j+1] = pairs[j].getNumber()+" "; for (int j = 0; j < pairs.length; j++) headers[0] = _("Board"); String[] headers = new String[pairs.length+1]; FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.##"); Pair[] pairs = pairv.toArray(new Pair[0]); Board[] boards = boardv.toArray(new Board[0]); Collections.sort(pairv, new PairNumberComparer()); Collections.sort(boardv, new BoardNumberComparer()); } throw new MovementVerificationException(setsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { grouping = Integer.parseInt(setsize); try { if (null != setsize && setsize.length() >= 0) int grouping = 0; { public static void matrix(List pairv, List boardv, TablePrinter tabular, String setsize) throws MovementVerificationException } modifiedpairs = true; p.total(boards); for (Pair p: pairs) { public static void total(List pairs, List boards) } modifiedboards = true; b.parimp(); for (Board b: boards) { public static void parimp(List boards) throws ScoreException } tabular.gap(); tabular.print(headers, matrix); matrix[0][2] = format.format(usimps-themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][1] = format.format(themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][0] = format.format(usimps, tmp, field).toString(); tmp = new StringBuffer(); String[][] matrix = new String[1][3]; StringBuffer tmp; FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.##"); headers[2] = _("Difference"); headers[1] = _("Them IMPs"); headers[0] = _("Us IMPs"); String[] headers = new String[3]; } themimps += -res[0]; else usimps += res[0]; if (res[0] > 0) double[] res = b.sumimp(prefix, teams);adøsäεœŒnO=ã©G(Í ’ u j T Þ Ð ˜ W ? 7 2 Æ Á © ˆ \ @ (  ý á Ë ² ™ ‰ k K !  ú â Ì ° š h X :  ëç®srZH& êά–‘vB'ϵ‰i:# óÜÅ®~N7 íÍž‡nW@)â²›„I)úãË´†V&ø÷ lines.add(line); line[7] = ex[9]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[7].equals("0") ? "" : ex[7]; line[4] = ex[5]; line[3] = ex[4]; line[2] = ex[3]; line[1] = _("N"); line[0] = ex[0]; String[] line = new String[ex.length-2]; String[] ex = h.export(); } else if (h.getNS().startsWith(p.getNumber()+".")) { lines.add(line); line[8] = ex[9]; line[7] = ex[6].equals("0") ? "" : ex[6]; line[6] = ex[7].equals("0") ? "" : ex[7]; line[5] = ex[5]; line[4] = ex[4]; line[3] = ex[3]; line[2] = ex[1]; line[1] = _("EW"); line[0] = ex[0]; String[] line = new String[ex.length-1]; String[] ex = h.export(); } else if (h.getEW().equals(p.getNumber())) { lines.add(line); line[8] = ex[8]; line[7] = ex[7].equals("0") ? "" : ex[7]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[5]; line[4] = ex[4]; line[3] = ex[3]; line[2] = ex[2]; line[1] = _("NS"); line[0] = ex[0]; String[] line = new String[ex.length-1]; String[] ex = h.export(); if (h.getNS().equals(p.getNumber())) { for (Hand h: hands) { Collections.sort(hands, new HandNSComparer()); List hands = b.getHands(); for (Board b: boards) { Vector lines = new Vector(); tabular.header(header); } header += ", "+n; for (String n: p.getNames()) { header += p.getNumber(); header = _("Pair "); else header = _("Player "); if (p.getNames().length == 1) String header; for (Pair p: pairs) { Collections.sort(boards, new BoardNumberComparer()); Collections.sort(pairs, new PairNumberComparer()); } if (Debug.debug) Debug.print("Individual"); : _("MPs:")}; ximp ? _("IMPs") "", _("Score:"), _("Tricks"), _("By"), _("Contract"), _("Dir"), _("Board"), headers = new String[] { } else { if (Debug.debug) Debug.print("Pairs"); : _("MPs:")}; ximp ? _("IMPs") "", _("Score:"), _("Tricks"), _("By"), _("Contract"), _("VS"), _("Dir"), _("Board"), headers = new String[] { if (pairs.get(0).getNames().length > 1) { if (0 == pairs.size()) return; String[] headers; { public static void scorecards(List pairs, List boards, TablePrinter tabular, boolean ximp) } } tabular.gap(); tabular.print(headers, lines.toArray(new String[0][])); tabular.header(_("Board: ")+b.getNumber()); else tabular.header(_("Board: ")+b.getNumber()+" [ "+b.getParContract()+" by "+b.getPar().getDeclarer()+" ]"); if (withpar) } lines.add(line); System.arraycopy(ex, 1, line, 0, line.length); String[] line = new String[ex.length-1]; String[] ex = h.export(); for (Hand h: hands) { Collections.sort(hands, new HandNSComparer()); List hands = b.getHands(); Vector lines = new Vector(); for (Board b: boards) { Collections.sort(boards, new BoardNumberComparer()); "" }; : _("MPs:"), ximp ? _("IMPs") "", _("Score:"), _("Tricks"), _("By"), _("Contract"), adDìeǧxaI2Ô¤v;ì Õ ½ ¦ x H   ê ± ‘ b K 3   î ¾ Ž w ` Y S N   ý ø ÷ ö € { 6 ñ å ™ v H Α†qO#ƾ¢‚Z9ëÐÅ™phLGÐËL0ûŸš ﲄƒedV/üõÑЦcìë MessageFormat.format(_("Must have at least {0} competitors to award local points in this event"), if (ps.length < scale.minPairs(arity)) throw new ScoreException( // check we have enough to give LPs npairs = originaltables * arity; else npairs = ps.length; if (-1 == originaltables) int arity = ps[0].getNames().length; int npairs; if (ps.length == 0) return; Pair[] ps = pairs.toArray(new Pair[0]); Collections.sort(pairs, new PairPercentageComparer()); // sort pairs in order { public static void localpoint(List pairs, List boards, MasterPointScale scale, int originaltables) throws ScoreException } modifiedpairs = true; } p.setPercentage(p.getPercentage()-handicap+normalize); double handicap = handicaps.get(p); for (Pair p: pairs) { if (null == handicaps) throw new ScoreException(_("Must supply a handicap file before calculating handicapped scores")); { public static void handicap(List pairs, Map handicaps, double normalize) throws ScoreException } return pairhandicaps; } pairhandicaps.put(p, handicap); handicap /= (double) names.length; } handicap += v; if (null == v) v = 50.0; Double v = handicaps.get(n); for (String n: names) { String[] names = p.getNames(); double handicap = 0.0; for (Pair p: pairs) { } throw new ScoreException(_("Failure in reading handicap file: ")+IOe.getMessage()); if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { in.close(); } handicaps.put(values[0], new Double(values[1])); if (values.length != 2) throw new ScoreException(_("Malformed handicap line: ")+Arrays.deepToString(values)); String[] values = in.getValues(); while (in.readRecord()) { CsvReader in = new CsvReader(new InputStreamReader(handicapfile)); try { Map pairhandicaps = new HashMap(); Map handicaps = new HashMap(); { public static Map readHandicapData(List pairs, InputStream handicapfile) throws ScoreException } } tabular.gap(); tabular.print(headers, lines.toArray(new String[0][])); } } } lines.add(line); line[7] = ex[9]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[7].equals("0") ? "" : ex[7]; line[4] = ex[5]; line[3] = ex[4]; line[2] = ex[3]; line[1] = _("W"); line[0] = ex[0]; String[] line = new String[ex.length-2]; String[] ex = h.export(); } else if (h.getEW().endsWith("."+p.getNumber())) { lines.add(line); line[7] = ex[9]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[7].equals("0") ? "" : ex[7]; line[4] = ex[5]; line[3] = ex[4]; line[2] = ex[3]; line[1] = _("E"); line[0] = ex[0]; String[] line = new String[ex.length-2]; String[] ex = h.export(); } else if (h.getEW().startsWith(p.getNumber()+".")) { lines.add(line); line[7] = ex[9]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[7].equals("0") ? "" : ex[7]; line[4] = ex[5]; line[3] = ex[4]; line[2] = ex[3]; line[1] = _("S"); line[0] = ex[0]; String[] line = new String[ex.length-2]; String[] ex = h.export(); } else if (h.getNS().endsWith("."+p.getNumber())) {ad¢_±°{UЦû µ f @ ?  Ý É ¬ Y :  º ’ Q ( Å p O D <   ‚ } D   ѬŒk\;ãÆ¾­Œ_G"ùçǼœ›cbR3ݰz^SH+zq@ Í{HGð˜Y:/.îØÓÒ¢¡ public static boolean modifiedpairs = false; } tabulate.gap(); tabulate.print(header, results.toArray(new String[0][])); } results.set(i, n); System.arraycopy(r, r.length-2, n, r.length-1, 2); if (Debug.debug) Debug.print("Printing handicap "+n[r.length-2]+" for "+p); n[r.length-2] = format.format(handicapdata.get(p), tmp, field).toString(); StringBuffer tmp = new StringBuffer(); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.#"); System.arraycopy(r, 0, n, 0, r.length-2); String[] n = new String[r.length+1]; String[] r = results.get(i); Pair p = pairs.get(i); for (int i = 0; i < pairs.size(); i++) { if (handicaps) results.add(p.export()); for (Pair p: pairs) else } results.add(b); System.arraycopy(a, 5, b, 4, a.length-5); System.arraycopy(a, 0, b, 0, 4); String[] b = new String[a.length-1]; String[] a = p.export(); for (Pair p: pairs) { if (ximp) String[] header = headerv.toArray(new String[0]); headerv.add(_("LPs")); else headerv.add(_("OPs")); if (orange) } headerv.add(_("%age")); headerv.add(_("h'cap")); if (handicaps) headerv.add(_("MPs")); else { headerv.add(_("IMPs")); if (ximp) } headerv.add(""); for (int i = 1; i < Pair.getMaxNames(); i++) headerv.add(_("Names")); headerv.add(_("Pair")); } else { headerv.add(_("Name")); headerv.add(_("Num")); if (Pair.getMaxNames() == 1) { Vector headerv = new Vector(); Collections.sort(pairs, new PairPercentageComparer()); Vector results = new Vector(); { public static void results(List pairs, TablePrinter tabulate, boolean orange, boolean ximp, Map handicapdata, boolean handicaps) } modifiedpairs = true; } } ps[j].setLPs(award); new Object[] { award, ps[j].getNumber(), ps[j].getLPs() })); MessageFormat.format(_("Calculated {0} LPs for pair {1} but data says {2}."), throw new ScoreException( if (ps[j].getLPs() != 0 && ps[j].getLPs() != award) for (int j = a; j <= i; j++) { if (award < scale.getMin() && award > 0) award = scale.getMin(); double award = Math.ceil(total / (1.0+i-a)); total += LPs[++i]; while (i+1 < ps.length && ps[i].getPercentage()==ps[i+1].getPercentage()) int total = LPs[i]; int a = i; for (int i = 0; i < ps.length && i < awarded; i++) { // award LPs, splitting on draws else LPs[i] = (int) Math.ceil(lp); if (lp > scale.getMax(boards.size())) LPs[i] = scale.getMax(boards.size()); for (int i = 0; i < LPs.length && i < awarded; i++, lp -= rate) double lp = top; if (Debug.debug) Debug.print(Debug.DEBUG, "Awarding LPs to "+ps.length+" pairs, top is "+top+" rate is "+rate+" number receiving LPs: "+awarded); double rate = scale.getRate(arity); double top = scale.getTop(npairs, arity, boards.size()); int awarded = scale.numberAwards(npairs, arity, boards.size()); int[] LPs = new int[ps.length]; // calculate LP scale based on number of pairs new Object[] { new Integer(scale.minPairs(arity)) }));ad½dÏΤŸ“wJ. ÞÓšP)Û µ d :  ç ½ b 4 þ Ï h 8  ß Ï ¢ u D  Ñ Ÿ x F / ýå›]L9Ùçœ_3 Ô¨Œ€\ öÚÏα–•Wß‹€ON°¥¤CBÜÂrcï½¼ tabular = new AsciiTablePrinter(out); if (format.length == 1) out = new PrintStream(new FileOutputStream(format[format.length-1])); else out = System.out; if ("-".equals(format[format.length-1])) PrintStream out; String[] format = options.get("--output").split(":"); TablePrinter tabular = null; Map ecatsoptions = new ECatsOptionsMap(options.get("--ecats-options")); } handicapdata = readHandicapData(pairs, new FileInputStream(options.get("--handicapdata"))); if (null != options.get("--handicapdata")) { Map handicapdata = null; } readTrickData(boards, new FileInputStream(options.get("--trickdata"))); if (null != options.get("--trickdata")) { pairs = readPairs(new FileInputStream(args[i+2]), boards); boards = readBoards(new FileInputStream(args[i+1])); List pairs; List boards; } System.exit(1); syntax(); System.out.println(_("You must specify boards.csv and names.csv")); if (args.length < (i+3)) { } System.exit(1); MasterPointScale.printScales(); if (null != options.get("--print-mpscales")) { } System.exit(1); ECatsOptionsMap.printOptions(); if (null != options.get("--print-ecats-options")) { } System.exit(1); syntax(); if (null != options.get("--help")) { } commands.add(args[i]); } else } System.exit(1); syntax(); System.out.println(_("Error: unknown option ")+opt[0]); } else { options.put(opt[0], opt[1]); else options.put(opt[0], "true"); if (opt.length == 1) if (options.containsKey(opt[0])) { if (Debug.debug) Debug.print(Arrays.asList(opt)); String[] opt = args[i].split("="); else if (args[i].startsWith("--")) { if ("--".equals(args[i])) break; for (i = 0; i < args.length; i++) { int i; options.put("--original-entry", "-1"); options.put("--mpscale", null); options.put("--print-mpscales", null); options.put("--print-ecats-options", null); options.put("--ecats-export-dir", null); options.put("--ecats-options", null); options.put("--handicap-normalizer", "0.0"); options.put("--handicapdata", null); options.put("--trickdata", null); options.put("--with-handicaps", null); options.put("--with-par", null); options.put("--setsize", null); options.put("--teamprefix", ""); options.put("--teamsize", null); options.put("--title", _("Salliere Duplicate Bridge Scorer: Results")); options.put("--ximp", null); options.put("--orange", null); options.put("--help", null); options.put("--output", "-"); HashMap options = new HashMap(); Vector commands = new Vector(); } Debug.setThrowableTraces(true); Debug.loadConfig(f); if (f.exists()) File f = new File("debug.conf"); if (Debug.debug) { try { { public static void main(String[] args) public static boolean modifiedboards = false;ad Åiâ¯jF0¯®“N/¶ µ ¡ n W <  î ß Å § ƒ    ” s O .  ÷ ò ñ ] X < % $ è ç Ó Ç œ p D óëä©tCóÔ¹ŠWE&÷º °¥˜—LG5òÐ̰‘ton)$õØÓÒVQ<÷ǘi#þãÅÄ for (Board b: boards) { double themimps = 0; double usimps = 0; } throw new ScoreException(teamsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { teams = Integer.parseInt(teamsize); try { if (null != teamsize && teamsize.length() >= 0) int teams = 4; { public static void teams(List boards, TablePrinter tabular, String prefix, String teamsize) throws ScoreException } modifiedboards = true; b.ximp(); for (Board b: boards) { public static void ximp(List boards) throws ScoreException } modifiedboards = true; b.matchPoint(played); for (Board b: boards) } played = b.getHands().size(); if (b.getHands().size() > played) for (Board b: boards) { int played = 0; { public static void matchpoint(List boards) throws ScoreException } } } new Object[] { boards[i].getNumber(), h.getNS(), h.getEW() })); MessageFormat.format(_("Board {0} was played by {1} and {2}, which I was not expecting."), throw new MovementVerificationException( if (!pairs.contains(h.getNS()+" "+h.getEW())) for (Hand h: boards[i].getHands()) // check the pairs } else { pairs.add(h.getNS()+" "+h.getEW()); for (Hand h: boards[i].getHands()) pairs.clear(); // reset the pairs if (0 == (i % size)) { for (int i = 0; i < boards.length; i++) { Set pairs = new TreeSet(); Board[] boards = boardv.toArray(new Board[0]); Collections.sort(boardv, new BoardNumberComparer()); } throw new MovementVerificationException(setsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { size = Integer.parseInt(setsize); try { int size = 0; if (null == setsize || setsize.length() == 0) return; b.validate(); for (Board b: boardv) { public static void verify(List boardv, String setsize) throws MovementVerificationException, BoardValidationException, HandParseException } modifiedboards = true; h.score(); if (!h.isAveraged()) for (Hand h: b.getHands()) for (Board b: boards) { public static void score(List boards) throws ScoreException, ContractParseException, HandParseException } } throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); } catch (IOException e) {} ftp.disconnect(); ftp.logout(); try { if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { ftp.disconnect(); ftp.logout(); System.err.println(_("Upload complete")); // log out if (!ftp.completePendingCommand()) throw new IOException(_("Uploading end file failed")); out.close(); out.print("End\r\n"); out = new PrintStream(ftp.storeFileStream(prefix+"E.txt")); // write end file if (!ftp.completePendingCommand()) throw new IOException(_("Uploading results failed")); System.err.println(); out.close(); doR(out, boards, session); out = new PrintStream(ftp.storeFileStream(prefix+"R.txt")); System.err.print(_("Uploading results")); // write boards filead¨ase`_ôó“B÷ Ö Õ “ Z V < ò Ñ ¦ s /  ã ¹ Y  ÷ ê „ ^ X W B ø å É  l _ %   ÿúùÓ‰$Þ³€<  Á®’H5(îÞÎÈÃÂ7¯ªonû辟—–‘2-~P1ãÕ¨§ Board b = boards.get(values[0]); } Debug.print(in.getCurrentRecord()+": "+Arrays.asList(values)); if (Debug.debug) { String[] values = in.getValues(); while (in.readRecord()) { try { Map boards = new HashMap(); CsvReader in = new CsvReader(new InputStreamReader(is)); { static List readBoards(InputStream is) throws IOException, BoardValidationException } } b.importTricks(s); if (null != (s = br.readLine())) String s; for (Board b: boards) { BufferedReader br = new BufferedReader(new InputStreamReader(trickdatafile)); Collections.sort(boards, new BoardNumberComparer()); { static void readTrickData(List boards, InputStream trickdatafile) throws IOException } } return points2-points1; if (Debug.debug) Debug.print(Debug.DEBUG, ob1.getNumber()+" have "+points1+" points and "+ob2.getNumber()+" have "+points2+" points."); } } points2++; points1++; if (Debug.debug) Debug.print(Debug.VERBOSE, "Draw"); } else { points2 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" win"); } else if (mp1 < mp2) { points1 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" win"); if (mp1 > mp2) { else mp2 = h.getEWMP(); || h.getNS().endsWith("."+ob2.getNumber())) mp2 = h.getNSMP(); || h.getNS().startsWith(ob2.getNumber()+".") if (h.getNS().equals(ob2.getNumber()) mp1 = h.getBoard().getTop() / 2; double mp1 = 0.0, mp2 = 0.0; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" not played, treating as average"); if (Debug.debug) Debug.print(Debug.VERBOSE, "Board: "+h.getNumber()); for (Hand h: hands2map.values()) { } } points2++; points1++; if (Debug.debug) Debug.print(Debug.VERBOSE, "Draw"); } else { points2 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" win"); } else if (mp1 < mp2) { points1 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" win"); if (mp1 > mp2) { } mp2 = h.getBoard().getTop() / 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" not played, treating as average"); } else { else mp2 = h.getEWMP(); || h.getNS().endsWith("."+ob2.getNumber())) mp2 = h.getNSMP(); || h.getNS().startsWith(ob2.getNumber()+".") if (h.getNS().equals(ob2.getNumber()) h = hands2map.remove(h.getNumber()); if (hands2map.containsKey(h.getNumber())) { else mp1 = h.getEWMP(); || h.getNS().endsWith("."+ob1.getNumber())) mp1 = h.getNSMP(); || h.getNS().startsWith(ob1.getNumber()+".") if (h.getNS().equals(ob1.getNumber()) double mp1 = 0.0, mp2 = 0.0; if (Debug.debug) Debug.print(Debug.VERBOSE, "Board: "+h.getNumber()); for (Hand h: hands1) { for (Hand h: hands2) hands2map.put(h.getNumber(), h); HashMap hands2map = new HashMap(); int points1 = 0, points2 = 0; if (Debug.debug) Debug.print(Debug.DEBUG, "Point-a-board count-back:"); and only for two-way ties. Matchpoint the matchpoints for these two pairs */ /* Only using this method here, so only works for all-play-all events without direct matches if (Debug.debug) Debug.print(Debug.INFO, "Splitting tie for "+ob1.getNumber()+" and "+ob2.getNumber()); } return 0; if (Debug.debug) Debug.print(Debug.INFO, "Can't Split tie for "+ob1.getNumber()+" and "+ob2.getNumber()+", because there are no hands");ad ¸fÕ«…i>üỪœ€c+æ É ¡ ‚ w o j i Û Ö Ê ª o   ê æ Ê t P : 9  Ò ¸ ¢ ¡ ƒ 9  ÿ þ ã ™ z d c A  ¦ž”UTCì¸K%$ Ú¦xwU!í̪s?õ¤€jå­hN8ع¸· System.err.println(); if (!ftp.completePendingCommand()) throw new IOException(_("Uploading pairs failed")); out.close(); doP(out, pairs); out = new PrintStream(ftp.storeFileStream(prefix+"P.txt")); System.err.print(_("Uploading pair details")); // write pairs file if (!ftp.completePendingCommand()) throw new IOException(_("Uploading club details failed")); out.close(); doC(out, boards, options); PrintStream out = new PrintStream(ftp.storeFileStream(prefix+"C.txt")); // write club file String prefix = prefixb.toString(); prefixb.append(phone.replaceAll(" ", "")); prefixb.append(clubName.replaceAll(" ", "")); prefixb.append(session); prefixb.append('0'); for (int i = session.length(); i < 6; i++) StringBuffer prefixb = new StringBuffer(); // calculate file prefix String phone = options.get("phone"); String clubName = options.get("clubName"); String session = options.get("session"); // get options ftp.enterLocalPassiveMode(); ftp.setFileType(FTPClient.BINARY_FILE_TYPE); ftp.changeWorkingDirectory(ECATS_UPLOAD_DIR); ftp.login(ECATS_USERNAME, ECATS_PASSWORD); ftp.connect(ECATS_SERVER); try { FTPClient ftp = new FTPClient(); // connect System.err.println(_("Uploading scores to ECATS")); { public static void uploadToECATS(List boards, List pairs, Map options) throws ScoreException } System.err.println(_("ECATS files have been written. Email the files C.txt, P.txt, R.txt and E.txt to results@simpairs.com")); } throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { out.close(); out.print("End\r\n"); out = new PrintStream(new FileOutputStream(exportdir+"/E.txt")); // write end file out.close(); doR(out, boards, session); out = new PrintStream(new FileOutputStream(exportdir+"/R.txt")); // write boards file out.close(); doP(out, pairs); out = new PrintStream(new FileOutputStream(exportdir+"/P.txt")); // write pairs file out.close(); doC(out, boards, options); PrintStream out = new PrintStream(new FileOutputStream(exportdir+"/C.txt")); // write club file String session = options.get("session"); System.err.println(_("Exporting scores in ECATS format to ")+exportdir); exportdir = new File (".").getCanonicalPath(); if (null == exportdir) try { { public static void exportToECATS(List boards, List pairs, Map options, String exportdir) throws ScoreException } } } out.print("\r\n"); out.print("0"); //spare = 0 out.print("\t"); out.print("0"); //spare = 0 out.print("\t"); out.print(session); // session number again out.print("\t"); out.print('"'); } } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60"); case Hand.AVERAGE_PLUS: switch (b.getEWAverage()) {ad•`㺑ƒZO*äßÞˆƒDØ Ë ¨ z 9  Ý Ò ­ › ™ f E  ñ È º q <  ÷    ™ “ Ž Š ‰ u p o   Ô º ” | { c ^  Þ/礟žJEÿã¿–ƒ~} ïͶzcϸw`𬕠out.print("\t"); out.print('"'+options.get("town")+'"'); //town (max 50 chars) out.print("\t"); out.print('"'+options.get("clubName")+'"'); //club name, compulsory (max 50 chars) out.print("\t"); out.print("\"true\""); // true iff contracts were recorded out.print("\t"); out.print("0"); // #boards/round (not important) out.print("\t"); out.print(""+boards.size()); // # boards played (not important) out.print("\t"); out.print("\"false\""); // true iff 2 winner movement out.print("\t"); out.print("1"); //spare = 1 out.print("\t"); // write C.txt { private static void doC(PrintStream out, List boards, Map options) } out.close(); out.writeRecord(h.export()); for (Hand h: b.getHands()) for (Board b: boards) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writeBoards(List boards, OutputStream os) throws IOException } System.out.println(" Formats: txt html htmlfrag pdf csv"); System.out.println(" Options: --help --output=[:]file --title=title --orange --setsize=N --ximp --with-par --trickdata= --handicapdata= --with-handicaps --handicap-normalizer= --ecats-options= --print-ecats-options --ecats-export-dir= --mpscale= --print-mpscales --teamsize=N --teamprefix= --original-entry=<#tables>"); System.out.println(" Commands: verify score matchpoint ximp parimp total handicap localpoint results matrix boards ecats-upload ecats-export scoreteams scorecards"); System.out.println("Usage: salliere [options] [commands] -- "); System.out.println("Salliere Duplicate Bridge Scorer - version "+version); .getImplementationVersion(); String version = Package.getPackage("cx.ath.matthew.salliere") { static void syntax() } out.close(); out.writeRecord(p.export()); for (Pair p: pairs) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writePairs(List pairs, OutputStream os) throws IOException } return pairs; } } } } pairmap.get(s).addHand(h); for (String s: ss) if (pairmap.containsKey(s)) ss = h.getEW().split("\\."); pairmap.get(s).addHand(h); for (String s: ss) if (pairmap.containsKey(s)) String[] ss = h.getNS().split("\\."); // probably individual } else { pairmap.get(h.getEW()).addHand(h); pairmap.get(h.getNS()).addHand(h); if (pairmap.containsKey(h.getNS())) { for (Hand h: b.getHands()) { for (Board b: boards) { if (null != boards) { in.close(); } catch (EOFException EOFe) {} } pairmap.put(p.getNumber(), p); pairs.add(p); Pair p = new Pair(values); if (Debug.debug) Debug.print(Arrays.asList(values)); String[] values = in.getValues(); while (in.readRecord()) { try { HashMap pairmap = new HashMap(); List pairs = new Vector(); CsvReader in = new CsvReader(new InputStreamReader(is)); { static List readPairs(InputStream is, List boards) throws IOException } return new ArrayList(boards.values()); in.close(); } catch (EOFException EOFe) {} } b.addHand(new Hand(values)); } boards.put(values[0], b); b = new Board(values[0]); if (null == b) {salliere-0.10/cx/ath/matthew/salliere/HandParseException.java0000644000175000017500000000176511306766521022750 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import java.io.IOException; @SuppressWarnings("serial") public class HandParseException extends IOException { public HandParseException(String message) { super(message); } } salliere-0.10/cx/ath/matthew/salliere/NoContractException.java0000644000175000017500000000166411306766530023153 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; @SuppressWarnings("serial") public class NoContractException extends Exception { public NoContractException() { } } salliere-0.10/cx/ath/matthew/salliere/Hand.java0000644000175000017500000004001111317362466020063 0ustar mjj29mjj29/* * Salliere Duplicate Bridge Scorer * * Copyright (C) 2007 Matthew Johnson * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License Version 2 as published by * the Free Software Foundation. This program is distributed in the hope that * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have received a * copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * To Contact me, please email src@matthew.ath.cx * */ package cx.ath.matthew.salliere; import cx.ath.matthew.debug.Debug; import static cx.ath.matthew.salliere.Gettext._; import java.text.DecimalFormat; import java.text.FieldPosition; import java.text.MessageFormat; import java.util.Arrays; public class Hand { public static final int AVERAGE=1; public static final int AVERAGE_MINUS=2; public static final int AVERAGE_PLUS=3; private boolean check_forced(String[] data, int ofs) { if ('!' == data[ofs].charAt(0)) { data[ofs] = data[ofs].substring(1); return true; } else return false; } String number = ""; String ns = ""; String ew = ""; String contract = ""; char declarer = ' '; int tricks; double nsscore; double ewscore; boolean forced_nsscore; boolean forced_ewscore; double nsmp; double ewmp; boolean forced_nsmp; boolean forced_ewmp; int ewavetype; int nsavetype; Board board; public Hand() { } @SuppressWarnings("fallthrough") public Hand(String[] data) throws HandParseException { if (data.length < 4) { String extra = ""; if (data.length > 0) extra = MessageFormat.format(_(" (board might be number {0})"), new Object[] { data[0] }); throw new HandParseException(_("Insufficient fields. I cannot parse a board without at least board number, pair numbers and contract")+extra); } this.number = data[0]; this.ns = data[1]; this.ew = data[2]; this.contract = data[3]; switch (data.length) { case 10: if (0 < data[9].length()) { forced_ewmp = check_forced(data, 9); try { this.ewmp = Double.parseDouble(data[9]); } catch (NumberFormatException NFe) { if (Debug.debug) Debug.print(NFe); throw new HandParseException(_("Invalid Number of Match Points: ")+data[9]); } } case 9: if (0 < data[8].length()) { forced_nsmp = check_forced(data, 8); try { this.nsmp = Double.parseDouble(data[8]); } catch (NumberFormatException NFe) { if (Debug.debug) Debug.print(NFe); throw new HandParseException(_("Invalid Number of Match Points: ")+data[8]); } } case 8: if (0 < data[7].length()) { forced_ewscore = check_forced(data, 7); try { this.ewscore = Double.parseDouble(data[7]); } catch (NumberFormatException NFe) { if (Debug.debug) Debug.print(NFe); String av = data[7].toLowerCase(); if (av.startsWith("av") && av.length() == 3) { if (Debug.debug) Debug.print("Parsing average, mode character is "+av.charAt(2)); switch (av.charAt(2)) { case '=': ewavetype = AVERAGE; break; case '+': ewavetype = AVERAGE_PLUS; break; case '-': ewavetype = AVERAGE_MINUS; break; default: throw new HandParseException(_("Invalid Average: ")+data[7]); } } else throw new HandParseException(_("Invalid Score: ")+data[7]); } } case 7: if (0 < data[6].length()) { forced_nsscore = check_forced(data, 6); try { this.nsscore = Double.parseDouble(data[6]); } catch (NumberFormatException NFe) { if (Debug.debug) Debug.print(NFe); String av = data[6].toLowerCase(); if (av.startsWith("av") && av.length() == 3) { if (Debug.debug) Debug.print("Parsing average, mode character is "+av.charAt(2)); switch (av.charAt(2)) { case '=': nsavetype = AVERAGE; break; case '+': nsavetype = AVERAGE_PLUS; break; case '-': nsavetype = AVERAGE_MINUS; break; default: throw new HandParseException(_("Invalid Average: ")+data[6]); } } else throw new HandParseException(_("Invalid Score: ")+data[6]); } } case 6: if (0 < data[5].length()) try { this.tricks = Integer.parseInt(data[5]); } catch (NumberFormatException NFe) { if (Debug.debug) Debug.print(NFe); throw new HandParseException(_("Invalid Number of Tricks: ")+data[5]); } case 5: if (data[4].length() > 0) this.declarer = data[4].charAt(0); } } @SuppressWarnings("fallthrough") public void score() throws ScoreException, ContractParseException, HandParseException { String[] n = number.split(":"); String[] v = n[n.length-1].split(";"); int num = 0; try { num = Integer.parseInt(v[0]); } catch (NumberFormatException NFe) { if (Debug.debug) Debug.print(NFe); throw new HandParseException(_("Invalid Hand Number: ")+number); } int vul = Contract.NONE; if (v.length == 1) { switch (num%16) { // ns case 4: case 7: case 10: case 13: vul |= Contract.EAST; case 2: case 5: case 12: case 15: vul |= Contract.NORTH; break; // ew case 3: case 6: case 9: case 0: vul |= Contract.EAST; break; } } else { // split options String[] opts = v[1].split(","); for (String opt: opts) { String[] keyval = opt.split("="); // manual vulnerability if (keyval[0].toLowerCase().equals("vul") && 2 == keyval.length) { if (keyval[1].toLowerCase().equals("ew")) vul = Contract.EAST; else if (keyval[1].toLowerCase().equals("ns")) vul = Contract.NORTH; else if (keyval[1].toLowerCase().equals("all")) vul = Contract.NORTH | Contract.EAST; } } } if (Debug.debug) Debug.print("number="+number+", num="+num+", n="+Arrays.asList(n)+", v="+Arrays.asList(v)+", vul="+vul); Contract c; try { c = new Contract(contract, declarer, vul, tricks); if (!forced_nsscore) { if (nsscore != 0 && nsscore != c.getNSScore()) throw new ScoreException( MessageFormat.format( _("Calculated score as {0} for NS but hand says {1}."), new Object[] { c.getNSScore(), this })); nsscore = c.getNSScore(); } if (!forced_ewscore) { if (ewscore != 0 && ewscore != c.getEWScore()) throw new ScoreException( MessageFormat.format( _("Calculated score as {0} for EW but hand says {1}."), new Object[] { c.getEWScore(), this })); ewscore = c.getEWScore(); } if (tricks != 0 && tricks != c.getTricks()) throw new ScoreException( MessageFormat.format( _("Calculated tricks as {0} but hand says {1}."), new Object[] { c.getTricks(), this })); tricks = c.getTricks(); contract = c.getContract(); declarer = c.getDeclarer(); if (Debug.debug) Debug.print(this); } catch (NoContractException NCe) { if (Debug.debug) Debug.print(NCe); /* not assigning scores on hands which have no contract. Must be averages or something. */ } } @SuppressWarnings("fallthrough") public void check() throws HandParseException { try { if (tricks > 13) throw new HandParseException(MessageFormat.format(_("Cannot take {0} tricks!"), new Object[] { tricks })); Contract c = new Contract(contract, declarer, 0, tricks); if (!c.isPassOut()) switch (declarer) { case 'n': case 's': case 'e': case 'w': case 'N': case 'S': case 'E': case 'W': break; default: throw new HandParseException(MessageFormat.format(_("On board {0} declarer should be one of NSEW, it is actually {1}."), new Object[] { number, declarer})); } } catch (ContractParseException CPe) { if (Debug.debug) Debug.print(CPe); throw new HandParseException(MessageFormat.format(_("Failed to parse contract on board {0}: {1}"), new Object[] { number, contract})); } catch (NoContractException NCe) { if (Debug.debug) Debug.print(NCe); /* not assigning scores on hands which have no contract. Must be averages or something. */ } } public String getNumber() { return number; } public String getNS() { return ns; } public String getEW() { return ew; } public String getContract() { return contract; } public double getNSMP() { return nsmp; } public double getEWMP() { return ewmp; } public double getEWScore() { return ewscore; } public double getNSScore() { return nsscore; } public int getTricks() { return tricks; } public char getDeclarer() { return declarer; } public boolean isAveraged() { return !(0 == ewavetype && 0 == nsavetype); } public int getEWAverage() { return ewavetype; } public int getNSAverage() { return nsavetype; } public boolean hasForcedNSMP() { return forced_nsmp; } public boolean hasForcedEWMP() { return forced_ewmp; } public boolean hasForcedNSScore() { return forced_nsscore; } public boolean hasForcedEWScore() { return forced_ewscore; } public Board getBoard() { return board; } public void setBoard(Board b) { board = b; } public void setNSMP(double mp) { nsmp = mp; } public void setEWMP(double mp) { ewmp = mp; } public void setNumber(String number) { this.number = number; } public void setNS(String ns) { this.ns = ns; } public void setEW(String ew) { this.ew = ew; } public void setContract(String contract) { this.contract = contract; } public void setEWScore(double ewscore) { this.ewscore = ewscore; } public void setNSScore(double nsscore) { this.nsscore = nsscore; } public void setTricks(int tricks) { this.tricks = tricks; } public void setDeclarer(char declarer) { this.declarer = declarer; } public void setEWScore(String ewscore) throws HandParseException { if (0 < ewscore.length()) try { this.ewscore = Double.parseDouble(ewscore); } catch (NumberFormatException NFe) { if (Debug.debug) Debug.print(NFe); String av = ewscore.toLowerCase(); if (av.startsWith("av") && av.length() == 3) switch (av.charAt(2)) { case '=': ewavetype = AVERAGE; break; case '+': ewavetype = AVERAGE_PLUS; break; case '-': ewavetype = AVERAGE_MINUS; break; default: throw new HandParseException(_("Invalid Average: ")+ewscore); } else throw new HandParseException(_("Invalid Score: ")+ewscore); } } public void setNSScore(String nsscore) throws HandParseException { if (0 < nsscore.length()) try { this.nsscore = Double.parseDouble(nsscore); } catch (NumberFormatException NFe) { if (Debug.debug) Debug.print(NFe); String av = nsscore.toLowerCase(); if (av.startsWith("av") && av.length() == 3) switch (av.charAt(2)) { case '=': nsavetype = AVERAGE; break; case '+': nsavetype = AVERAGE_PLUS; break; case '-': nsavetype = AVERAGE_MINUS; break; default: throw new HandParseException(_("Invalid Average: ")+nsscore); } else throw new HandParseException(_("Invalid Score: ")+nsscore); } } public void setForcedNSMP(boolean forced) { forced_nsmp = forced; } public void setForcedEWMP(boolean forced) { forced_ewmp = forced; } public void setForcedNSScore(boolean forced) { forced_nsscore = forced; } public void setForcedEWScore(boolean forced) { forced_ewscore = forced; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append(number); sb.append(": "); sb.append(ns); sb.append(_(" vs ")); sb.append(ew); sb.append(" "); sb.append(contract); sb.append(_(" by ")); sb.append(declarer); sb.append(_(" making ")); sb.append(tricks); sb.append(_(" tricks. ")); sb.append(nsscore); if (forced_nsscore) sb.append(_(" (forced)")); sb.append(_(" to NS ")); sb.append(ewscore); if (forced_ewscore) sb.append(_(" (forced)")); sb.append(_(" to EW ")); sb.append(nsmp); if (forced_nsmp) sb.append(_(" (forced)")); sb.append(_(" to NS ")); sb.append(ewmp); if (forced_ewmp) sb.append(_(" (forced)")); sb.append(_(" to EW.")); return sb.toString(); } public String[] export() { String[] rv = new String[10]; rv[0] = number; rv[1] = ns; rv[2] = ew; rv[3] = contract; rv[4] = ""+declarer; rv[5] = ""+tricks; DecimalFormat format = new DecimalFormat("0.##"); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); StringBuffer tmp = new StringBuffer(); switch (nsavetype) { case AVERAGE: rv[6] = "av="; break; case AVERAGE_MINUS: rv[6] = "av-"; break; case AVERAGE_PLUS: rv[6] = "av+"; break; default: rv[6] = (forced_nsscore?"!":"") + format.format(nsscore, tmp, field).toString(); break; } tmp = new StringBuffer(); switch (ewavetype) { case AVERAGE: rv[7] = "av="; break; case AVERAGE_MINUS: rv[7] = "av-"; break; case AVERAGE_PLUS: rv[7] = "av+"; break; default: rv[7] = (forced_ewscore?"!":"") + format.format(ewscore, tmp, field).toString(); break; } tmp = new StringBuffer(); rv[8] = (forced_nsmp?"!":"") + format.format(nsmp, tmp, field).toString(); tmp = new StringBuffer(); rv[9] = (forced_ewmp?"!":"") + format.format(ewmp, tmp, field).toString(); return rv; } } salliere-0.10/cx/ath/matthew/salliere/.Salliere.java.swo0000644000175000017500000004000011326446676021642 0ustar mjj29mjj29b0VIM 7.1t>K.Û2mjj29qadesh~mjj29/scm/salliere/cx/ath/matthew/salliere/Salliere.java 3210#"! Utp ÿoÿÿÿÿapþÿÿÿaÑýÿÿÿ^2üÿÿÿeûÿÿÿjõúÿÿÿd_ùÿÿÿkÃøÿÿÿ^.÷ÿÿÿaŒöÿÿÿIí6adLoüØÔ®«`Ây,à • H ( % ó ð ì ë Ê É © ‰ ˆ e 4 3   æ É ´ ” s W 5  ü Ù ½ ¡ ˆ j M 3   ð Ö ½ } ] \ F D Ì‘TÙØ˜kcAýõðﮩzrL&Ñ¥‰b65  ÍÈ›“WOJIÔÌ1-ŸžwPO if (hands1.size() == 0 || hands2.size() == 0) { List hands2 = ob2.getHands(); List hands1 = ob1.getHands(); if (ob2.getPercentage() != ob1.getPercentage()) return (int) ((ob2.getPercentage()-ob1.getPercentage())*100.0); // no need to split tie if (Debug.debug) Debug.print(Debug.VERBOSE, "Comparing "+ob1.getNumber()+"["+ob1.getPercentage()+"] and "+ob2.getNumber()+"["+ob2.getPercentage()+"]"); { public int compare(Pair ob1, Pair ob2) { static class PairPercentageComparer implements Comparator } } return ob1.getNumber().compareTo(ob2.getNumber()); { public int compare(Pair ob1, Pair ob2) { static class PairNumberComparer implements Comparator } } return num1-num2; int num2 = Integer.parseInt(v[0]); v = n[n.length-1].split(";"); n = n2.split(":"); int num1 = Integer.parseInt(v[0]); String[] v = n[n.length-1].split(";"); String[] n = n1.split(":"); String n2 = ob2.getNumber(); String n1 = ob1.getNumber(); { public int compare(Board ob1, Board ob2) { static class BoardNumberComparer implements Comparator } } return n1.compareTo(n2); String n2 = ob2.getNS(); String n1 = ob1.getNS(); { public int compare(Hand ob1, Hand ob2) { static class HandNSComparer implements Comparator public static final String ECATS_PROGRAM_VERSION = "5.6.28"; public static final String ECATS_UPLOAD_DIR = "\\sims"; public static final String ECATS_PASSWORD = "simsuser32"; public static final String ECATS_USERNAME = "simsuser"; public static final String ECATS_SERVER = "sims.ecats.co.uk"; // data gathered from looking at ecats-ftp sessions{public class Salliereimport java.text.MessageFormat;import java.text.FieldPosition;import java.text.DecimalFormat;import java.util.Vector;import java.util.TreeSet;import java.util.Set;import java.util.Map;import java.util.List;import java.util.HashMap;import java.util.Comparator;import java.util.Collections;import java.util.Arrays;import java.util.ArrayList;import java.io.PrintStream;import java.io.OutputStreamWriter;import java.io.OutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.InputStream;import java.io.FileOutputStream;import java.io.FileInputStream;import java.io.File;import java.io.EOFException;import java.io.BufferedReader;import org.apache.commons.net.ftp.FTPClient;import static cx.ath.matthew.salliere.Gettext._;import cx.ath.matthew.debug.Debug;import com.csvreader.CsvWriter;import com.csvreader.CsvReader;package cx.ath.matthew.salliere; */ * * To Contact me, please email src@matthew.ath.cx * * Boston, MA 02111-1307, USA. * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * copy of the GNU General Public License along with this program; if not, * GNU General Public License for more details. You should have received a * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * the Free Software Foundation. This program is distributed in the hope that * under the terms of the GNU General Public License Version 2 as published by * This program is free software; you can redistribute it and/or modify it * * Copyright (C) 2007 Matthew Johnson * * Salliere Duplicate Bridge Scorer/* adÞ R í®•vh]\B,&Æ©iK/Ü Ñ z a Y T R Q } } } System.exit(1); System.out.println(_("Salliere failed to compute results: ")+e.getMessage()); } Debug.print(Debug.ERR, e); Debug.setThrowableTraces(true); if (Debug.debug) { } catch (Exception e) { writePairs(pairs, new FileOutputStream(args[i+2])); if (modifiedpairs) writeBoards(boards, new FileOutputStream(args[i+1])); if (modifiedboards) out.close(); tabular.close(); } } System.exit(1); syntax(); System.out.println(_("Bad Command: ")+command); else {salliere-0.10/cx/ath/matthew/salliere/.Salliere.java.swn0000644000175000017500000017000011326447044021633 0ustar mjj29mjj29b0VIM 7.1t>K.H3mjj29qadesh~mjj29/scm/salliere/cx/ath/matthew/salliere/Salliere.javautf-8 3210#"! Utp ÿoapÑCñ^2ejõ d_ kà ^. aŒ Ií6adLoüØÔ®«`Ây,à • H ( % ó ð ì ë Ê É © ‰ ˆ e 4 3   æ É ´ ” s W 5  ü Ù ½ ¡ ˆ j M 3   ð Ö ½ } ] \ F D Ì‘TÙØ˜kcAýõðﮩzrL&Ñ¥‰b65  ÍÈ›“WOJIÔÌ1-ŸžwPO if (hands1.size() == 0 || hands2.size() == 0) { List hands2 = ob2.getHands(); List hands1 = ob1.getHands(); if (ob2.getPercentage() != ob1.getPercentage()) return (int) ((ob2.getPercentage()-ob1.getPercentage())*100.0); // no need to split tie if (Debug.debug) Debug.print(Debug.VERBOSE, "Comparing "+ob1.getNumber()+"["+ob1.getPercentage()+"] and "+ob2.getNumber()+"["+ob2.getPercentage()+"]"); { public int compare(Pair ob1, Pair ob2) { static class PairPercentageComparer implements Comparator } } return ob1.getNumber().compareTo(ob2.getNumber()); { public int compare(Pair ob1, Pair ob2) { static class PairNumberComparer implements Comparator } } return num1-num2; int num2 = Integer.parseInt(v[0]); v = n[n.length-1].split(";"); n = n2.split(":"); int num1 = Integer.parseInt(v[0]); String[] v = n[n.length-1].split(";"); String[] n = n1.split(":"); String n2 = ob2.getNumber(); String n1 = ob1.getNumber(); { public int compare(Board ob1, Board ob2) { static class BoardNumberComparer implements Comparator } } return n1.compareTo(n2); String n2 = ob2.getNS(); String n1 = ob1.getNS(); { public int compare(Hand ob1, Hand ob2) { static class HandNSComparer implements Comparator public static final String ECATS_PROGRAM_VERSION = "5.6.28"; public static final String ECATS_UPLOAD_DIR = "\\sims"; public static final String ECATS_PASSWORD = "simsuser32"; public static final String ECATS_USERNAME = "simsuser"; public static final String ECATS_SERVER = "sims.ecats.co.uk"; // data gathered from looking at ecats-ftp sessions{public class Salliereimport java.text.MessageFormat;import java.text.FieldPosition;import java.text.DecimalFormat;import java.util.Vector;import java.util.TreeSet;import java.util.Set;import java.util.Map;import java.util.List;import java.util.HashMap;import java.util.Comparator;import java.util.Collections;import java.util.Arrays;import java.util.ArrayList;import java.io.PrintStream;import java.io.OutputStreamWriter;import java.io.OutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.InputStream;import java.io.FileOutputStream;import java.io.FileInputStream;import java.io.File;import java.io.EOFException;import java.io.BufferedReader;import org.apache.commons.net.ftp.FTPClient;import static cx.ath.matthew.salliere.Gettext._;import cx.ath.matthew.debug.Debug;import com.csvreader.CsvWriter;import com.csvreader.CsvReader;package cx.ath.matthew.salliere; */ * * To Contact me, please email src@matthew.ath.cx * * Boston, MA 02111-1307, USA. * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * copy of the GNU General Public License along with this program; if not, * GNU General Public License for more details. You should have received a * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * the Free Software Foundation. This program is distributed in the hope that * under the terms of the GNU General Public License Version 2 as published by * This program is free software; you can redistribute it and/or modify it * * Copyright (C) 2007 Matthew Johnson * * Salliere Duplicate Bridge Scorer/* adÞ R í®•vh]\B,&Æ©iK/Ü Ñ z a Y T R Q } } } System.exit(1); System.out.println(_("Salliere failed to compute results: ")+e.getMessage()); } Debug.print(Debug.ERR, e); Debug.setThrowableTraces(true); if (Debug.debug) { } catch (Exception e) { writePairs(pairs, new FileOutputStream(args[i+2])); if (modifiedpairs) writeBoards(boards, new FileOutputStream(args[i+1])); if (modifiedboards) out.close(); tabular.close(); } } System.exit(1); syntax(); System.out.println(_("Bad Command: ")+command); else {ad‹  㺑ƒZO*äßÞˆƒDØ Ë ¨ z 9  Ý Ò ­ › ™ f E  & â ¹ « Ž b I '  ë É Â ¼ · ³ ² ž ™ ˜ H C ý ã ½ ª ¥ ¤ Œ ‡ B  ¶X·6óîíì™”N2åÒÍÌojU>ɲlUƯV?ûäœ out.print('"'+options.get("county")+'"'); //county (max 50 chars) out.print("\t"); out.print('"'+options.get("town")+'"'); //town (max 50 chars) out.print("\t"); out.print('"'+options.get("clubName")+'"'); //club name, compulsory (max 50 chars) out.print("\t"); out.print("\"true\""); // true iff contracts were recorded out.print("\t"); out.print("0"); // #boards/round (not important) out.print("\t"); out.print(""+boards.size()); // # boards played (not important) out.print("\t"); out.print("\"false\""); // true iff 2 winner movement out.print("\t"); out.print("1"); //spare = 1 out.print("\t"); // write C.txt { private static void doC(PrintStream out, List boards, Map options) } out.close(); out.writeRecord(h.export()); for (Hand h: b.getHands()) for (Board b: boards) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writeBoards(List boards, OutputStream os) throws IOException } System.out.println(" Formats: txt html htmlfrag pdf csv"); System.out.println(" Options: --help --output=[:]file --title=title --orange --setsize=N --ximp --with-par --trickdata= --handicapdata= --with-handicaps --handicap-normalizer= --ecats-options= --print-ecats-options --mpscale= --print-mpscales --teamsize=N --teamprefix= --original-entry=<#tables>"); System.out.println(" Commands: verify score matchpoint ximp parimp total handicap localpoint results matrix boards ecats-upload scoreteams scorecards"); System.out.println("Usage: salliere [options] [commands] -- "); System.out.println("Salliere Duplicate Bridge Scorer - version "+version); .getImplementationVersion(); String version = Package.getPackage("cx.ath.matthew.salliere") { static void syntax() } out.close(); out.writeRecord(p.export()); for (Pair p: pairs) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writePairs(List pairs, OutputStream os) throws IOException } return pairs; } } } } pairmap.get(s).addHand(h); for (String s: ss) ss = h.getEW().split("\\."); pairmap.get(s).addHand(h); for (String s: ss) String[] ss = h.getNS().split("\\."); // probably individual } else { pairmap.get(h.getEW()).addHand(h); pairmap.get(h.getNS()).addHand(h); if (pairmap System.err.println("NS="+h.getNS()); for (Hand h: b.getHands()) { for (Board b: boards) { if (null != boards) { in.close(); } catch (EOFException EOFe) {} } pairmap.put(p.getNumber(), p); pairs.add(p); Pair p = new Pair(values); if (Debug.debug) Debug.print(Arrays.asList(values)); String[] values = in.getValues(); while (in.readRecord()) { try { HashMap pairmap = new HashMap(); List pairs = new Vector(); CsvReader in = new CsvReader(new InputStreamReader(is)); { static List readPairs(InputStream is, List boards) throws IOException } return new ArrayList(boards.values()); in.close(); } catch (EOFException EOFe) {} } b.addHand(new Hand(values)); } boards.put(values[0], b); b = new Board(values[0]); if (null == b) {adFfCÕ¬ƒuX,ñε“Œ†}|hcb Ç ­ ‡ t o n V Q Ñ € " ½ ¸ · ¶ c ^  üدœ—–94æÏ“|6èÑy  Å®f out.print('"'+options.get("county")+'"'); //county (max 50 chars) out.print("\t"); out.print('"'+options.get("town")+'"'); //town (max 50 chars) out.print("\t"); out.print('"'+options.get("clubName")+'"'); //club name, compulsory (max 50 chars) out.print("\t"); out.print("\"true\""); // true iff contracts were recorded out.print("\t"); out.print("0"); // #boards/round (not important) out.print("\t"); out.print(""+boards.size()); // # boards played (not important) out.print("\t"); out.print("\"false\""); // true iff 2 winner movement out.print("\t"); out.print("1"); //spare = 1 out.print("\t"); // write C.txt { private static void doC(PrintStream out, List boards, Map options) } out.close(); out.writeRecord(h.export()); for (Hand h: b.getHands()) for (Board b: boards) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writeBoards(List boards, OutputStream os) throws IOException } System.out.println(" Formats: txt html htmlfrag pdf csv"); System.out.println(" Options: --help --output=[:]file --title=title --orange --setsize=N --ximp --with-par --trickdata= --handicapdata= --with-handicaps --handicap-normalizer= --ecats-options= --print-ecats-options --mpscale= --print-mpscales --teamsize=N --teamprefix= --original-entry=<#tables>"); System.out.println(" Commands: verify score matchpoint ximp parimp total handicap localpoint results matrix boards ecats-upload scoreteams scorecards"); System.out.println("Usage: salliere [options] [commands] -- "); System.out.println("Salliere Duplicate Bridge Scorer - version "+version); .getImplementationVersion(); String version = Package.getPackage("cx.ath.matthew.salliere") { static void syntax() } out.close(); out.writeRecord(p.export()); for (Pair p: pairs) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writePairs(List pairs, OutputStream os) throws IOException } return pairs; } } } } pairmap.get(s).addHand(h); for (String s: ss) ss = h.getEW().split("\\."); pairmap.get(s).addHand(h); for (String s: ss) String[] ss = h.getNS().split("\\."); // probably individual } else { pairmap.get(h.getEW()).addHand(h); pairmap.get(h.getNS()).addHand(h); if (pairmap.containsKey(h.getNS())) {ad –^éw`³œZCý æ ¸ ¡ W @ ¹ ¢ c L ú á Ü Û ˜ | b < " ü â ª h 3  ó Ù ³ ™ 1   ¸³”mP& Û¾„g0ñÔ²•eHûÒµsVøµ˜Y<ýàÄ¢ƒX.ìÁ›d>-ز–• break; out.print("60"); case Hand.AVERAGE_PLUS: switch (b.getEWAverage()) { } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60"); case Hand.AVERAGE_PLUS: switch (b.getNSAverage()) { out.print("A"); if (b.isAveraged()) { out.print('"'); out.print("\t"); out.print(""+b.getEWMP()); // double, recalculated out.print("\t"); out.print(""+b.getNSMP()); // double, recalculated out.print("\t"); out.print("\""+b.getDeclarer()+'"'); // text, not used out.print("\t"); out.print("\""+b.getTricks()+'"'); // text, not used out.print("\t"); out.print('"'+b.getContract()+'"'); // text, not used out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print(""+(int) b.getEWScore()); out.print("\t"); out.print(""+(int) b.getNSScore()); out.print("\t"); out.print(b.getEW()); out.print("\t"); out.print(b.getNS()); out.print("\t"); out.print(b.getNumber()); // int, non zero out.print("\t"); out.print("\"\""); // section, not used == "" out.print("\t"); out.print("\"\""); // spare == "" out.print("\t"); out.print("0"); // spare == 0 out.print("\t"); for (Hand b: bd.getHands()) { for (Board bd: boards) { { private static void doR(PrintStream out, List boards, String session) } } out.print("\r\n"); out.print("\"NS\""); // for a 2 winner movement, set this to the direction they were sitting. out.print("\t"); out.print('"'+names[1]+'"'); out.print("\t"); out.print('"'+names[0]+'"'); out.print("\t"); out.print('"'+names[0]+" & "+names[1]+'"'); String[] names = p.getNames(); out.print("\t"); out.print(p.getNumber()); // pair number (int) out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); for (Pair p: pairs) { { private static void doP(PrintStream out, List pairs) } out.print("\r\n"); out.print('"'+options.get("event")+'"'); // event name, text (max 50 chars) out.print("\t"); out.print('"'+options.get("date")+'"'); // "dd/mm/yyyy" out.print("\t"); out.print('"'+ECATS_PROGRAM_VERSION+'"'); // program version. Important. My program? their program? this number seems to work... out.print("\t"); out.print(options.get("session")); //session #, compulsory, numeric out.print("\t"); out.print("\"false\""); //spare = false out.print("\t"); out.print('"'+options.get("email")+'"'); //email (max 50 chars) out.print("\t"); out.print('"'+options.get("fax")+'"'); //fax (max 50 chars) out.print("\t"); out.print('"'+options.get("phone")+'"'); //phone, compulsory (max 50 chars) out.print("\t"); out.print('"'+options.get("name")+'"'); //name (max 50 chars) out.print("\t"); out.print('"'+options.get("country")+'"'); //country, compulsory, spelling agreed in advance (max 50 chars) out.print("\t");ad¹eÕ¯“xRA3úÂ¥}`8r m a A  ´ ³ } a ç Ñ Ð ³ i O 9 8  Ð ¬ – • z 0  û ú Ø ¬ = 5 4 ¯ª©¨+&ìëÚ³§ƒOâ¼»£q=츄cA Ö©¨Œ;š™|DÿåÏoPO1þ¹¸ out = new PrintStream(ftp.storeFileStream(prefix+"R.txt")); System.err.print(_("Uploading results")); // write boards file System.err.println(); if (!ftp.completePendingCommand()) throw new IOException(_("Uploading pairs failed")); out.close(); doP(out, pairs); out = new PrintStream(ftp.storeFileStream(prefix+"P.txt")); System.err.print(_("Uploading pair details")); // write pairs file if (!ftp.completePendingCommand()) throw new IOException(_("Uploading club details failed")); out.close(); doC(out, boards, options); PrintStream out = new PrintStream(ftp.storeFileStream(prefix+"C.txt")); // write club file String prefix = prefixb.toString(); prefixb.append(phone.replaceAll(" ", "")); prefixb.append(clubName.replaceAll(" ", "")); prefixb.append(session); prefixb.append('0'); for (int i = session.length(); i < 6; i++) StringBuffer prefixb = new StringBuffer(); // calculate file prefix String phone = options.get("phone"); String clubName = options.get("clubName"); String session = options.get("session"); // get options ftp.enterLocalPassiveMode(); ftp.setFileType(FTPClient.BINARY_FILE_TYPE); ftp.changeWorkingDirectory(ECATS_UPLOAD_DIR); ftp.login(ECATS_USERNAME, ECATS_PASSWORD); ftp.connect(ECATS_SERVER); try { FTPClient ftp = new FTPClient(); // connect System.err.println(_("Uploading scores to ECATS")); { public static void uploadToECATS(List boards, List pairs, Map options) throws ScoreException } System.err.println(_("ECATS files have been written. Email the files C.txt, P.txt, R.txt and E.txt to results@simpairs.com")); } throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { out.close(); out.print("End\r\n"); out = new PrintStream(new FileOutputStream(exportdir+"/E.txt")); // write end file out.close(); doR(out, boards, session); out = new PrintStream(new FileOutputStream(exportdir+"/R.txt")); // write boards file out.close(); doP(out, pairs); out = new PrintStream(new FileOutputStream(exportdir+"/P.txt")); // write pairs file out.close(); doC(out, boards, options); PrintStream out = new PrintStream(new FileOutputStream(exportdir+"/C.txt")); // write club file String session = options.get("session"); System.err.println(_("Exporting scores in ECATS format to ")+exportdir); exportdir = new File (".").getCanonicalPath(); if (null == exportdir) try { { public static void exportToECATS(List boards, List pairs, Map options, String exportdir) throws ScoreException } } } out.print("\r\n"); out.print("0"); //spare = 0 out.print("\t"); out.print("0"); //spare = 0 out.print("\t"); out.print(session); // session number again out.print("\t"); out.print('"'); } } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS:adÑjÜÆ§ED)äůLK7í Ò ° „ u [ =  ª ¢ œ * % å Ä ª ˆ ‡ ó î Ò » º ~ } i ] 2  Ú ‰ z ? Ù©‰jO íÛ¼P¡F;3.-âÝÁ¨‹†…@; ïêémhSÞ¯€:/.úÜ«’tfE=ôÑÐ headers[1] = _("Them IMPs"); headers[0] = _("Us IMPs"); String[] headers = new String[3]; } themimps += -res[0]; else usimps += res[0]; if (res[0] > 0) double[] res = b.sumimp(prefix, teams); for (Board b: boards) { double themimps = 0; double usimps = 0; } throw new ScoreException(teamsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { teams = Integer.parseInt(teamsize); try { if (null != teamsize && teamsize.length() >= 0) int teams = 4; { public static void teams(List boards, TablePrinter tabular, String prefix, String teamsize) throws ScoreException } modifiedboards = true; b.ximp(); for (Board b: boards) { public static void ximp(List boards) throws ScoreException } modifiedboards = true; b.matchPoint(); for (Board b: boards) { public static void matchpoint(List boards) throws ScoreException } } } new Object[] { boards[i].getNumber(), h.getNS(), h.getEW() })); MessageFormat.format(_("Board {0} was played by {1} and {2}, which I was not expecting."), throw new MovementVerificationException( if (!pairs.contains(h.getNS()+" "+h.getEW())) for (Hand h: boards[i].getHands()) // check the pairs } else { pairs.add(h.getNS()+" "+h.getEW()); for (Hand h: boards[i].getHands()) pairs.clear(); // reset the pairs if (0 == (i % size)) { for (int i = 0; i < boards.length; i++) { Set pairs = new TreeSet(); Board[] boards = boardv.toArray(new Board[0]); Collections.sort(boardv, new BoardNumberComparer()); } throw new MovementVerificationException(setsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { size = Integer.parseInt(setsize); try { int size = 0; if (null == setsize || setsize.length() == 0) return; b.validate(); for (Board b: boardv) { public static void verify(List boardv, String setsize) throws MovementVerificationException, BoardValidationException, HandParseException } modifiedboards = true; h.score(); if (!h.isAveraged()) for (Hand h: b.getHands()) for (Board b: boards) { public static void score(List boards) throws ScoreException, ContractParseException, HandParseException } } throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); } catch (IOException e) {} ftp.disconnect(); ftp.logout(); try { if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { ftp.disconnect(); ftp.logout(); System.err.println(_("Upload complete")); // log out if (!ftp.completePendingCommand()) throw new IOException(_("Uploading end file failed")); out.close(); out.print("End\r\n"); out = new PrintStream(ftp.storeFileStream(prefix+"E.txt")); // write end file if (!ftp.completePendingCommand()) throw new IOException(_("Uploading results failed")); System.err.println(); out.close(); doR(out, boards, session);ad¶dܤX@ó°K+ß Þ ¸ £ ž V Q 5  þ ý » ¶ œ ‚ f a ` Ò Í µ r @  â Ž ƒ ‚ G  Ù ¨ § o # " íΠml9öïÚÙ³‚9Ì–SÜ‘{SE:ݬyIïäÈÇž†~y ßʵ™ƒjQA#ò·¶µ Collections.sort(boards, new BoardNumberComparer()); "" }; : _("MPs:"), ximp ? _("IMPs") "", _("Score:"), _("Tricks"), _("By"), _("Contract"), _("EW"), _("NS"), String[] headers = new String[] { { public static void boardbyboard(List boards, TablePrinter tabular, boolean ximp, boolean withpar) } } tabular.gap(); tabular.print(headers, matrix); start += grouping; } matrix[matrix.length-1][j+1] = format.format(sums[j], tmp, field).toString(); matrix[matrix.length-2][j+1] = " "; StringBuffer tmp = new StringBuffer(); for (int j = 0; j < sums.length; j++) { matrix[matrix.length-1][0] = _("Total"); matrix[matrix.length-2][0] = " "; } } matrix[i][j+1] = " "; } else sums[j] += boards[i+start].getMPs(pairs[j].getNumber()); matrix[i][j+1] = format.format(boards[i+start].getMPs(pairs[j].getNumber()), tmp, field).toString(); if (boards[i+start].played(pairs[j].getNumber())) { StringBuffer tmp = new StringBuffer(); for (int j = 0; j < pairs.length; j++) { matrix[i][0] = boards[i+start].getNumber(); for (int i = 0; i+start < boards.length && i < grouping; i++) { float[] sums = new float[pairs.length]; while (start < boards.length) { int start = 0; String[][] matrix = new String[grouping+2][pairs.length+1]; if (0 == grouping) grouping = boards.length; headers[j+1] = pairs[j].getNumber()+" "; for (int j = 0; j < pairs.length; j++) headers[0] = _("Board"); String[] headers = new String[pairs.length+1]; FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.##"); Pair[] pairs = pairv.toArray(new Pair[0]); Board[] boards = boardv.toArray(new Board[0]); Collections.sort(pairv, new PairNumberComparer()); Collections.sort(boardv, new BoardNumberComparer()); } throw new MovementVerificationException(setsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { grouping = Integer.parseInt(setsize); try { if (null != setsize && setsize.length() >= 0) int grouping = 0; { public static void matrix(List pairv, List boardv, TablePrinter tabular, String setsize) throws MovementVerificationException } modifiedpairs = true; p.total(boards); for (Pair p: pairs) { public static void total(List pairs, List boards) } modifiedboards = true; b.parimp(); for (Board b: boards) { public static void parimp(List boards) throws ScoreException } tabular.gap(); tabular.print(headers, matrix); matrix[0][2] = format.format(usimps-themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][1] = format.format(themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][0] = format.format(usimps, tmp, field).toString(); tmp = new StringBuffer(); String[][] matrix = new String[1][3]; StringBuffer tmp; FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.##"); headers[2] = _("Difference");ad Ëkâ¨~F'Ì‘tiSÝ Ï — V > 6 1 Å À ˜ € j U 9 # ñ á à £ j / .   â Ç ¿ ¦ Š h R M 2 þ ã ¾ ‹ q E % ö߯¯˜j: óÜ©‰ZC*üåΞnW@93.óáÝØ×Ö`[ÑÅyV(®qfQ/¦ž‚b:ðËÊ if (null == v) v = 50.0; Double v = handicaps.get(n); for (String n: names) { String[] names = p.getNames(); double handicap = 0.0; for (Pair p: pairs) { } throw new ScoreException(_("Failure in reading handicap file: ")+IOe.getMessage()); if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { in.close(); } handicaps.put(values[0], new Double(values[1])); if (values.length != 2) throw new ScoreException(_("Malformed handicap line: ")+Arrays.deepToString(values)); String[] values = in.getValues(); while (in.readRecord()) { CsvReader in = new CsvReader(new InputStreamReader(handicapfile)); try { Map pairhandicaps = new HashMap(); Map handicaps = new HashMap(); { public static Map readHandicapData(List pairs, InputStream handicapfile) throws ScoreException } } tabular.gap(); tabular.print(headers, lines.toArray(new String[0][])); } } } lines.add(line); line[8] = ex[9]; line[7] = ex[6].equals("0") ? "" : ex[6]; line[6] = ex[7].equals("0") ? "" : ex[7]; line[5] = ex[5]; line[4] = ex[4]; line[3] = ex[3]; line[2] = ex[1]; line[1] = _("EW"); line[0] = ex[0]; String[] line = new String[ex.length-1]; String[] ex = h.export(); } else if (h.getEW().equals(p.getNumber())) { lines.add(line); line[8] = ex[8]; line[7] = ex[7].equals("0") ? "" : ex[7]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[5]; line[4] = ex[4]; line[3] = ex[3]; line[2] = ex[2]; line[1] = _("NS"); line[0] = ex[0]; String[] line = new String[ex.length-1]; String[] ex = h.export(); if (h.getNS().equals(p.getNumber())) { for (Hand h: hands) { Collections.sort(hands, new HandNSComparer()); List hands = b.getHands(); for (Board b: boards) { Vector lines = new Vector(); tabular.header(header); } header += ", "+n; for (String n: p.getNames()) { header += p.getNumber(); header = _("Pair "); else header = _("Player "); if (p.getNames().length == 1) String header; for (Pair p: pairs) { Collections.sort(boards, new BoardNumberComparer()); Collections.sort(pairs, new PairNumberComparer()); : _("MPs:")}; ximp ? _("IMPs") "", _("Score:"), _("Tricks"), _("By"), _("Contract"), _("VS"), _("Dir"), _("Board"), String[] headers = new String[] { { public static void scorecards(List pairs, List boards, TablePrinter tabular, boolean ximp) } } tabular.gap(); tabular.print(headers, lines.toArray(new String[0][])); tabular.header(_("Board: ")+b.getNumber()); else tabular.header(_("Board: ")+b.getNumber()+" [ "+b.getParContract()+" by "+b.getPar().getDeclarer()+" ]"); if (withpar) } lines.add(line); System.arraycopy(ex, 1, line, 0, line.length); String[] line = new String[ex.length-1]; String[] ex = h.export(); for (Hand h: hands) { Collections.sort(hands, new HandNSComparer()); List hands = b.getHands(); Vector lines = new Vector(); for (Board b: boards) {ad"®^åÚ®…}a\åàaEØ Ð ´ ¯ & !  Ç ™ ˜ z y k D (  æ å » x  ² ± | V  Ñ §  üÈySR+ðÜ¿lMÍ¥d;؃bWO3.-•W俟~oN,öÙÑÀŸ’rZ5 úÚϯ®­ headerv.add(_("LPs")); else headerv.add(_("OPs")); if (orange) } headerv.add(_("%age")); headerv.add(_("h'cap")); if (handicaps) headerv.add(_("MPs")); else { headerv.add(_("IMPs")); if (ximp) } headerv.add(""); for (int i = 1; i < Pair.getMaxNames(); i++) headerv.add(_("Names")); headerv.add(_("Pair")); } else { headerv.add(_("Name")); headerv.add(_("Num")); if (Pair.getMaxNames() == 1) { Vector headerv = new Vector(); Collections.sort(pairs, new PairPercentageComparer()); Vector results = new Vector(); { public static void results(List pairs, TablePrinter tabulate, boolean orange, boolean ximp, Map handicapdata, boolean handicaps) } modifiedpairs = true; } } ps[j].setLPs(award); new Object[] { award, ps[j].getNumber(), ps[j].getLPs() })); MessageFormat.format(_("Calculated {0} LPs for pair {1} but data says {2}."), throw new ScoreException( if (ps[j].getLPs() != 0 && ps[j].getLPs() != award) for (int j = a; j <= i; j++) { if (award < scale.getMin() && award > 0) award = scale.getMin(); double award = Math.ceil(total / (1.0+i-a)); total += LPs[++i]; while (i+1 < ps.length && ps[i].getPercentage()==ps[i+1].getPercentage()) int total = LPs[i]; int a = i; for (int i = 0; i < ps.length && i < awarded; i++) { // award LPs, splitting on draws else LPs[i] = (int) Math.ceil(lp); if (lp > scale.getMax(boards.size())) LPs[i] = scale.getMax(boards.size()); for (int i = 0; i < awarded; i++, lp -= rate) double lp = top; if (Debug.debug) Debug.print(Debug.DEBUG, "Awarding LPs to "+ps.length+" pairs, top is "+top+" rate is "+rate+" number receiving LPs: "+awarded); double rate = scale.getRate(arity); double top = scale.getTop(npairs, arity, boards.size()); int awarded = scale.numberAwards(npairs, arity, boards.size()); int[] LPs = new int[ps.length]; // calculate LP scale based on number of pairs new Object[] { new Integer(scale.minPairs(arity)) })); MessageFormat.format(_("Must have at least {0} competitors to award local points in this event"), if (ps.length < scale.minPairs(arity)) throw new ScoreException( // check we have enough to give LPs npairs = originaltables * arity; else npairs = ps.length; if (-1 == originaltables) int arity = ps[0].getNames().length; int npairs; if (ps.length == 0) return; Pair[] ps = pairs.toArray(new Pair[0]); Collections.sort(pairs, new PairPercentageComparer()); // sort pairs in order { public static void localpoint(List pairs, List boards, MasterPointScale scale, int originaltables) throws ScoreException } modifiedpairs = true; } p.setPercentage(p.getPercentage()-handicap+normalize); double handicap = handicaps.get(p); for (Pair p: pairs) { if (null == handicaps) throw new ScoreException(_("Must supply a handicap file before calculating handicapped scores")); { public static void handicap(List pairs, Map handicaps, double normalize) throws ScoreException } return pairhandicaps; } pairhandicaps.put(p, handicap); handicap /= (double) names.length; } handicap += v;ad¯aÈÇ·˜sBßø­kjT"ÿ Ö ¥ o 2 à ­ ¬ U ý ¾ Ÿ ” “ S = 8 7  Ö Õ « ¦ š ~ Q 5  å Ú ¡ W 0 â¼kAîÄ”i;Ö¤o?æÖ©|KئM6좆dS@àÊ®£f:Û¯® MasterPointScale.printScales(); if (null != options.get("--print-mpscales")) { } System.exit(1); ECatsOptionsMap.printOptions(); if (null != options.get("--print-ecats-options")) { } System.exit(1); syntax(); if (null != options.get("--help")) { } commands.add(args[i]); } else } System.exit(1); syntax(); System.out.println(_("Error: unknown option ")+opt[0]); } else { options.put(opt[0], opt[1]); else options.put(opt[0], "true"); if (opt.length == 1) if (options.containsKey(opt[0])) { if (Debug.debug) Debug.print(Arrays.asList(opt)); String[] opt = args[i].split("="); else if (args[i].startsWith("--")) { if ("--".equals(args[i])) break; for (i = 0; i < args.length; i++) { int i; options.put("--original-entry", "-1"); options.put("--mpscale", null); options.put("--print-mpscales", null); options.put("--print-ecats-options", null); options.put("--ecats-export-dir", null); options.put("--ecats-options", null); options.put("--handicap-normalizer", "0.0"); options.put("--handicapdata", null); options.put("--trickdata", null); options.put("--with-handicaps", null); options.put("--with-par", null); options.put("--setsize", null); options.put("--teamprefix", ""); options.put("--teamsize", null); options.put("--title", _("Salliere Duplicate Bridge Scorer: Results")); options.put("--ximp", null); options.put("--orange", null); options.put("--help", null); options.put("--output", "-"); HashMap options = new HashMap(); Vector commands = new Vector(); } Debug.setThrowableTraces(true); Debug.loadConfig(f); if (f.exists()) File f = new File("debug.conf"); if (Debug.debug) { try { { public static void main(String[] args) public static boolean modifiedboards = false; public static boolean modifiedpairs = false; } tabulate.gap(); tabulate.print(header, results.toArray(new String[0][])); } results.set(i, n); System.arraycopy(r, r.length-2, n, r.length-1, 2); if (Debug.debug) Debug.print("Printing handicap "+n[r.length-2]+" for "+p); n[r.length-2] = format.format(handicapdata.get(p), tmp, field).toString(); StringBuffer tmp = new StringBuffer(); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.#"); System.arraycopy(r, 0, n, 0, r.length-2); String[] n = new String[r.length+1]; String[] r = results.get(i); Pair p = pairs.get(i); for (int i = 0; i < pairs.size(); i++) { if (handicaps) results.add(p.export()); for (Pair p: pairs) else } results.add(b); System.arraycopy(a, 5, b, 4, a.length-5); System.arraycopy(a, 0, b, 0, 4); String[] b = new String[a.length-1]; String[] a = p.export(); for (Pair p: pairs) { if (ximp) String[] header = headerv.toArray(new String[0]);ad8IäÙØ´dN2'& îí¯kj7ã Ø × § ¦ p  ý ü › š t s 4  è Ê » i h G  Ü ª q A  ¾ € 3 ú²¢aK/$ÐÏ¥m͉É`ÐZ¤ß ?»8 else if ("scoreteams".equals(command)) teams(boards, tabular, options.get("--teamprefix"), options.get("--teamsize")); else if ("ecats-export".equals(command)) exportToECATS(boards, pairs, ecatsoptions, options.get("--ecats-export-dir")); else if ("ecats-upload".equals(command)) uploadToECATS(boards, pairs, ecatsoptions); else if ("parimp".equals(command)) parimp(boards); else if ("ximp".equals(command)) ximp(boards); else if ("handicap".equals(command)) handicap(pairs, handicapdata, Double.parseDouble(options.get("--handicap-normalizer"))); else if ("localpoint".equals(command)) localpoint(pairs, boards, MasterPointScale.getScale(options.get("--mpscale")), Integer.parseInt(options.get("--original-entry"))); else if ("scorecards".equals(command)) scorecards(pairs, boards, tabular, null != options.get("--ximp")); else if ("boards".equals(command)) boardbyboard(boards, tabular, null != options.get("--ximp"), null != options.get("--with-par")); else if ("matrix".equals(command)) matrix(pairs, boards, tabular, options.get("--setsize")); else if ("results".equals(command)) results(pairs, tabular, null != options.get("--orange"), null != options.get("--ximp"), handicapdata, null != options.get("--with-handicaps")); else if ("total".equals(command)) total(pairs, boards); else if ("matchpoint".equals(command)) matchpoint(boards); else if ("verify".equals(command)) verify(boards, options.get("--setsize")); if ("score".equals(command)) score(boards); for (String command: commands) { tabular.header(options.get("--title")); tabular.init(); } System.exit(1); syntax(); System.out.println(_("Unknown format: ")+format[0]); else { tabular = new PDFTablePrinter(options.get("--title"), out); else if ("pdf".equals(format[0].toLowerCase())) tabular = new HTMLFragTablePrinter(options.get("--title"), out); else if ("htmlfrag".equals(format[0].toLowerCase())) tabular = new HTMLTablePrinter(options.get("--title"), out); else if ("html".equals(format[0].toLowerCase())) tabular = new CSVTablePrinter(out); else if ("csv".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); else if ("txt".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); if (format.length == 1) out = new PrintStream(new FileOutputStream(format[format.length-1])); else out = System.out; if ("-".equals(format[format.length-1])) PrintStream out; String[] format = options.get("--output").split(":"); TablePrinter tabular = null; Map ecatsoptions = new ECatsOptionsMap(options.get("--ecats-options")); } handicapdata = readHandicapData(pairs, new FileInputStream(options.get("--handicapdata"))); if (null != options.get("--handicapdata")) { Map handicapdata = null; } readTrickData(boards, new FileInputStream(options.get("--trickdata"))); if (null != options.get("--trickdata")) { pairs = readPairs(new FileInputStream(args[i+2]), boards); boards = readBoards(new FileInputStream(args[i+1])); List pairs; List boards; } System.exit(1); syntax(); System.out.println(_("You must specify boards.csv and names.csv")); if (args.length < (i+3)) { } System.exit(1);ad¨ase`_ôó“B÷ Ö Õ “ Z V < ò Ñ ¦ s /  ã ¹ Y  ÷ ê „ ^ X W B ø å É  l _ %   ÿúùÓ‰$Þ³€<  Á®’H5(îÞÎÈÃÂ7¯ªonû辟—–‘2-~P1ãÕ¨§ Board b = boards.get(values[0]); } Debug.print(in.getCurrentRecord()+": "+Arrays.asList(values)); if (Debug.debug) { String[] values = in.getValues(); while (in.readRecord()) { try { Map boards = new HashMap(); CsvReader in = new CsvReader(new InputStreamReader(is)); { static List readBoards(InputStream is) throws IOException, BoardValidationException } } b.importTricks(s); if (null != (s = br.readLine())) String s; for (Board b: boards) { BufferedReader br = new BufferedReader(new InputStreamReader(trickdatafile)); Collections.sort(boards, new BoardNumberComparer()); { static void readTrickData(List boards, InputStream trickdatafile) throws IOException } } return points2-points1; if (Debug.debug) Debug.print(Debug.DEBUG, ob1.getNumber()+" have "+points1+" points and "+ob2.getNumber()+" have "+points2+" points."); } } points2++; points1++; if (Debug.debug) Debug.print(Debug.VERBOSE, "Draw"); } else { points2 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" win"); } else if (mp1 < mp2) { points1 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" win"); if (mp1 > mp2) { else mp2 = h.getEWMP(); || h.getNS().endsWith("."+ob2.getNumber())) mp2 = h.getNSMP(); || h.getNS().startsWith(ob2.getNumber()+".") if (h.getNS().equals(ob2.getNumber()) mp1 = h.getBoard().getTop() / 2; double mp1 = 0.0, mp2 = 0.0; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" not played, treating as average"); if (Debug.debug) Debug.print(Debug.VERBOSE, "Board: "+h.getNumber()); for (Hand h: hands2map.values()) { } } points2++; points1++; if (Debug.debug) Debug.print(Debug.VERBOSE, "Draw"); } else { points2 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" win"); } else if (mp1 < mp2) { points1 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" win"); if (mp1 > mp2) { } mp2 = h.getBoard().getTop() / 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" not played, treating as average"); } else { else mp2 = h.getEWMP(); || h.getNS().endsWith("."+ob2.getNumber())) mp2 = h.getNSMP(); || h.getNS().startsWith(ob2.getNumber()+".") if (h.getNS().equals(ob2.getNumber()) h = hands2map.remove(h.getNumber()); if (hands2map.containsKey(h.getNumber())) { else mp1 = h.getEWMP(); || h.getNS().endsWith("."+ob1.getNumber())) mp1 = h.getNSMP(); || h.getNS().startsWith(ob1.getNumber()+".") if (h.getNS().equals(ob1.getNumber()) double mp1 = 0.0, mp2 = 0.0; if (Debug.debug) Debug.print(Debug.VERBOSE, "Board: "+h.getNumber()); for (Hand h: hands1) { for (Hand h: hands2) hands2map.put(h.getNumber(), h); HashMap hands2map = new HashMap(); int points1 = 0, points2 = 0; if (Debug.debug) Debug.print(Debug.DEBUG, "Point-a-board count-back:"); and only for two-way ties. Matchpoint the matchpoints for these two pairs */ /* Only using this method here, so only works for all-play-all events without direct matches if (Debug.debug) Debug.print(Debug.INFO, "Splitting tie for "+ob1.getNumber()+" and "+ob2.getNumber()); } return 0; if (Debug.debug) Debug.print(Debug.INFO, "Can't Split tie for "+ob1.getNumber()+" and "+ob2.getNumber()+", because there are no hands");salliere-0.10/cx/ath/matthew/salliere/.MasterPointScale.java.swp0000644000175000017500000001000011327104562023277 0ustar mjj29mjj29b0VIM 7.1O>KP)±-mjj29qadesh~mjj29/scm/salliere/cx/ath/matthew/salliere/MasterPointScale.java 3210#"! Usalliere-0.10/cx/ath/matthew/salliere/.Salliere.java.swm0000644000175000017500000017000011327105003021615 0ustar mjj29mjj29b0VIM 7.1$NZKJ)9/mjj29qadesh~mjj29/scm/salliere/cx/ath/matthew/salliere/Salliere.javautf-8 3210#"! Utp ÿo ap aÑ ]2 f iõd^kÂ.-/\cŠIí6adLoüØÔ®«`Ây,à • H ( % ó ð ì ë Ê É © ‰ ˆ e 4 3   æ É ´ ” s W 5  ü Ù ½ ¡ ˆ j M 3   ð Ö ½ } ] \ F D Ì‘TÙØ˜kcAýõðﮩzrL&Ñ¥‰b65  ÍÈ›“WOJIÔÌ1-ŸžwPO if (hands1.size() == 0 || hands2.size() == 0) { List hands2 = ob2.getHands(); List hands1 = ob1.getHands(); if (ob2.getPercentage() != ob1.getPercentage()) return (int) ((ob2.getPercentage()-ob1.getPercentage())*100.0); // no need to split tie if (Debug.debug) Debug.print(Debug.VERBOSE, "Comparing "+ob1.getNumber()+"["+ob1.getPercentage()+"] and "+ob2.getNumber()+"["+ob2.getPercentage()+"]"); { public int compare(Pair ob1, Pair ob2) { static class PairPercentageComparer implements Comparator } } return ob1.getNumber().compareTo(ob2.getNumber()); { public int compare(Pair ob1, Pair ob2) { static class PairNumberComparer implements Comparator } } return num1-num2; int num2 = Integer.parseInt(v[0]); v = n[n.length-1].split(";"); n = n2.split(":"); int num1 = Integer.parseInt(v[0]); String[] v = n[n.length-1].split(";"); String[] n = n1.split(":"); String n2 = ob2.getNumber(); String n1 = ob1.getNumber(); { public int compare(Board ob1, Board ob2) { static class BoardNumberComparer implements Comparator } } return n1.compareTo(n2); String n2 = ob2.getNS(); String n1 = ob1.getNS(); { public int compare(Hand ob1, Hand ob2) { static class HandNSComparer implements Comparator public static final String ECATS_PROGRAM_VERSION = "5.6.28"; public static final String ECATS_UPLOAD_DIR = "\\sims"; public static final String ECATS_PASSWORD = "simsuser32"; public static final String ECATS_USERNAME = "simsuser"; public static final String ECATS_SERVER = "sims.ecats.co.uk"; // data gathered from looking at ecats-ftp sessions{public class Salliereimport java.text.MessageFormat;import java.text.FieldPosition;import java.text.DecimalFormat;import java.util.Vector;import java.util.TreeSet;import java.util.Set;import java.util.Map;import java.util.List;import java.util.HashMap;import java.util.Comparator;import java.util.Collections;import java.util.Arrays;import java.util.ArrayList;import java.io.PrintStream;import java.io.OutputStreamWriter;import java.io.OutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.InputStream;import java.io.FileOutputStream;import java.io.FileInputStream;import java.io.File;import java.io.EOFException;import java.io.BufferedReader;import org.apache.commons.net.ftp.FTPClient;import static cx.ath.matthew.salliere.Gettext._;import cx.ath.matthew.debug.Debug;import com.csvreader.CsvWriter;import com.csvreader.CsvReader;package cx.ath.matthew.salliere; */ * * To Contact me, please email src@matthew.ath.cx * * Boston, MA 02111-1307, USA. * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * copy of the GNU General Public License along with this program; if not, * GNU General Public License for more details. You should have received a * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * it will be useful, but WITHOUT ANY WARRANTY; without even the implied * the Free Software Foundation. This program is distributed in the hope that * under the terms of the GNU General Public License Version 2 as published by * This program is free software; you can redistribute it and/or modify it * * Copyright (C) 2007 Matthew Johnson * * Salliere Duplicate Bridge Scorer/* adW Ï }j+óåÚÙ¿©£…C&æ È ¬ € Y N ÷ Þ Ö Ñ Ï Î } } } System.exit(1); System.out.println(_("Salliere failed to compute results: ")+e.getMessage()); } Debug.print(Debug.ERR, e); Debug.setThrowableTraces(true); if (Debug.debug) { } catch (Exception e) { writePairs(pairs, new FileOutputStream(args[i+2])); if (modifiedpairs) writeBoards(boards, new FileOutputStream(args[i+1])); if (modifiedboards) out.close(); tabular.close(); } } System.exit(1); syntax(); System.out.println(_("Bad Command: ")+command); else { else if ("scoreteams".equals(command)) teams(boards, tabular, options.get("--teamprefix"), options.get("--teamsize"));adB /±‹Šc(÷¤…OÝ œ s  » š ‡ k f e Í È R Q  ÷ × ¶ § † d .  ø × Ê ª ’ m L D 2  headerv.add(_("OPs")); if (orange) } headerv.add(_("%age")); headerv.add(_("h'cap")); if (handicaps) headerv.add(_("MPs")); else { headerv.add(_("IMPs")); if (ximp) } headerv.add(""); for (int i = 1; i < Pair.getMaxNames(); i++) headerv.add(_("Names")); headerv.add(_("Pair")); } else { headerv.add(_("Name")); headerv.add(_("Num")); if (Pair.getMaxNames() == 1) { Vector headerv = new Vector(); Collections.sort(pairs, new PairPercentageComparer()); Vector results = new Vector(); { public static void results(List pairs, TablePrinter tabulate, boolean orange, boolean ximp, Map handicapdata, boolean handicaps) } modifiedpairs = true; } } ps[j].setLPs(award); new Object[] { award, ps[j].getNumber(), ps[j].getLPs() })); MessageFormat.format(_("Calculated {0} LPs for pair {1} but data says {2}."), throw new ScoreException( if (ps[j].getLPs() != 0 && ps[j].getLPs() != award) for (int j = a; j <= i; j++) { if (award < scale.getMin() && award > 0) award = scale.getMin(); double award = Math.ceil(total / (1.0+i-a)); total += LPs[++i]; while (i+1 < ps.length && ps[i].getPercentage()==ps[i+1].getPercentage()) int total = LPs[i]; int a = i; for (int i = 0; i < ps.length && i < awarded; i++) { // award LPs, splitting on draws else LPs[i] = (int) Math.ceil(lp); if (lp > scale.getMax(boards.size())) LPs[i] = scale.getMax(boards.size());adœh.ײ—Œ`7/—’÷ Ê Š ‚ f a Ø Ó ¶ y K J , +  ö Ú Ã ¼ ˜ — m * ³ d c .   ƒ Y Á®h=ÙžŠmûÅ{Sé†1ýáÜÛC>ÈÇ’mM,üÚ¤‡nM@ 㺨ˆ headerv.add(_("OPs")); if (orange) } headerv.add(_("%age")); headerv.add(_("h'cap")); if (handicaps) headerv.add(_("MPs")); else { headerv.add(_("IMPs")); if (ximp) } headerv.add(""); for (int i = 1; i < Pair.getMaxNames(); i++) headerv.add(_("Names")); headerv.add(_("Pair")); } else { headerv.add(_("Name")); headerv.add(_("Num")); if (Pair.getMaxNames() == 1) { Vector headerv = new Vector(); Collections.sort(pairs, new PairPercentageComparer()); Vector results = new Vector(); { public static void results(List pairs, TablePrinter tabulate, boolean orange, boolean ximp, Map handicapdata, boolean handicaps) } modifiedpairs = true; } } ps[j].setLPs(award); new Object[] { award, ps[j].getNumber(), ps[j].getLPs() })); MessageFormat.format(_("Calculated {0} LPs for pair {1} but data says {2}."), throw new ScoreException( if (ps[j].getLPs() != 0 && ps[j].getLPs() != award) for (int j = a; j <= i; j++) { if (award < scale.getMin() && award > 0) award = scale.getMin(); double award = Math.ceil(total / (1.0+i-a)); total += LPs[++i]; while (i+1 < ps.length && ps[i].getPercentage()==ps[i+1].getPercentage()) int total = LPs[i]; int a = i; for (int i = 0; i < ps.length && i < awarded; i++) { // award LPs, splitting on draws else LPs[i] = (int) Math.ceil(lp); if (lp > scale.getM for (int i = 0; i < Li < awarded; i++ for (int i = 0; i < LPs.length && i < awarded; i++, lp -= rate) double lp = top; if (Debug.debug) Debug.print(Debug.DEBUG, "Awarding LPs to "+ps.length+" pairs, top is "+top+" rate is "+rate+" number receiving LPs: "+awarded); double rate = scale.getRate(arity); double top = scale.getTop(npairs, arity, boards.size()); int awarded = scale.numberAwards(npairs, arity, boards.size()); int[] LPs = new int[ps.length]; // calculate LP scale based on number of pairs new Object[] { new Integer(scale.minPairs(arity)) })); MessageFormat.format(_("Must have at least {0} competitors to award local points in this event"), if (ps.length < scale.minPairs(arity)) throw new ScoreException( // check we have enough to give LPs npairs = originaltables * arity; else npairs = ps.length; if (-1 == originaltables) int arity = ps[0].getNames().length; int npairs; if (ps.length == 0) return; Pair[] ps = pairs.toArray(new Pair[0]); Collections.sort(pairs, new PairPercentageComparer()); // sort pairs in order { public static void localpoint(List pairs, List boards, MasterPointScale scale, int originaltables) throws ScoreException } modifiedpairs = true; } p.setPercentage(p.getPercentage()-handicap+normalize); double handicap = handicaps.get(p); for (Pair p: pairs) { if (null == handicaps) throw new ScoreException(_("Must supply a handicap file before calculating handicapped scores")); { public static void handicap(List pairs, Map handicaps, double normalize) throws ScoreException } return pairhandicaps; } pairhandicaps.put(p, handicap); handicap /= (double) names.length; } handicap += v; if (null == v) v = 50.0; Double v = handicaps.get(n);adWIÔ¸­¬ˆ8"ûúÝÂÁƒ?> · ¬ « { z D Ü Ñ Ð o n H G  î ¼ ž = <  é ° ~ E  Û ’ T  Άv5øîÕ¤£yAè¡]4¤.xî³tŽ else if ("ecats-export".equals(command)) exportToECATS(boards, pairs, ecatsoptions, options.get("--ecats-export-dir")); else if ("ecats-upload".equals(command)) uploadToECATS(boards, pairs, ecatsoptions); else if ("parimp".equals(command)) parimp(boards); else if ("ximp".equals(command)) ximp(boards); else if ("handicap".equals(command)) handicap(pairs, handicapdata, Double.parseDouble(options.get("--handicap-normalizer"))); else if ("localpoint".equals(command)) localpoint(pairs, boards, MasterPointScale.getScale(options.get("--mpscale")), Integer.parseInt(options.get("--original-entry"))); else if ("scorecards".equals(command)) scorecards(pairs, boards, tabular, null != options.get("--ximp")); else if ("boards".equals(command)) boardbyboard(boards, tabular, null != options.get("--ximp"), null != options.get("--with-par")); else if ("matrix".equals(command)) matrix(pairs, boards, tabular, options.get("--setsize")); else if ("results".equals(command)) results(pairs, tabular, null != options.get("--orange"), null != options.get("--ximp"), handicapdata, null != options.get("--with-handicaps")); else if ("total".equals(command)) total(pairs, boards); else if ("matchpoint".equals(command)) matchpoint(boards); else if ("verify".equals(command)) verify(boards, options.get("--setsize")); if ("score".equals(command)) score(boards); for (String command: commands) { tabular.header(options.get("--title")); tabular.init(); } System.exit(1); syntax(); System.out.println(_("Unknown format: ")+format[0]); else { tabular = new PDFTablePrinter(options.get("--title"), out); else if ("pdf".equals(format[0].toLowerCase())) tabular = new HTMLFragTablePrinter(options.get("--title"), out); else if ("htmlfrag".equals(format[0].toLowerCase())) tabular = new HTMLTablePrinter(options.get("--title"), out); else if ("html".equals(format[0].toLowerCase())) tabular = new CSVTablePrinter(out); else if ("csv".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); else if ("txt".equals(format[0].toLowerCase())) tabular = new AsciiTablePrinter(out); if (format.length == 1) out = new PrintStream(new FileOutputStream(format[format.length-1])); else out = System.out; if ("-".equals(format[format.length-1])) PrintStream out; String[] format = options.get("--output").split(":"); TablePrinter tabular = null; Map ecatsoptions = new ECatsOptionsMap(options.get("--ecats-options")); } handicapdata = readHandicapData(pairs, new FileInputStream(options.get("--handicapdata"))); if (null != options.get("--handicapdata")) { Map handicapdata = null; } readTrickData(boards, new FileInputStream(options.get("--trickdata"))); if (null != options.get("--trickdata")) { pairs = readPairs(new FileInputStream(args[i+2]), boards); boards = readBoards(new FileInputStream(args[i+1])); List pairs; List boards; } System.exit(1); syntax(); System.out.println(_("You must specify boards.csv and names.csv")); if (args.length < (i+3)) { } System.exit(1); MasterPointScale.printScales();ad¯cõÕÔœ›‹lGé³—Œd?>(ö Ó ª y C  ´ € ) Ñ ’ s h g '  Û ª ©  z n R % å ¹ ® u +  Þ¶?ë˜h=ÙªxC꺪}Pí¬zS! ØÀvZ8'îãâ´ž‚w:ò篮 if (null != options.get("--print-mpscales")) { } System.exit(1); ECatsOptionsMap.printOptions(); if (null != options.get("--print-ecats-options")) { } System.exit(1); syntax(); if (null != options.get("--help")) { } commands.add(args[i]); } else } System.exit(1); syntax(); System.out.println(_("Error: unknown option ")+opt[0]); } else { options.put(opt[0], opt[1]); else options.put(opt[0], "true"); if (opt.length == 1) if (options.containsKey(opt[0])) { if (Debug.debug) Debug.print(Arrays.asList(opt)); String[] opt = args[i].split("="); else if (args[i].startsWith("--")) { if ("--".equals(args[i])) break; for (i = 0; i < args.length; i++) { int i; options.put("--original-entry", "-1"); options.put("--mpscale", null); options.put("--print-mpscales", null); options.put("--print-ecats-options", null); options.put("--ecats-export-dir", null); options.put("--ecats-options", null); options.put("--handicap-normalizer", "0.0"); options.put("--handicapdata", null); options.put("--trickdata", null); options.put("--with-handicaps", null); options.put("--with-par", null); options.put("--setsize", null); options.put("--teamprefix", ""); options.put("--teamsize", null); options.put("--title", _("Salliere Duplicate Bridge Scorer: Results")); options.put("--ximp", null); options.put("--orange", null); options.put("--help", null); options.put("--output", "-"); HashMap options = new HashMap(); Vector commands = new Vector(); } Debug.setThrowableTraces(true); Debug.loadConfig(f); if (f.exists()) File f = new File("debug.conf"); if (Debug.debug) { try { { public static void main(String[] args) public static boolean modifiedboards = false; public static boolean modifiedpairs = false; } tabulate.gap(); tabulate.print(header, results.toArray(new String[0][])); } results.set(i, n); System.arraycopy(r, r.length-2, n, r.length-1, 2); if (Debug.debug) Debug.print("Printing handicap "+n[r.length-2]+" for "+p); n[r.length-2] = format.format(handicapdata.get(p), tmp, field).toString(); StringBuffer tmp = new StringBuffer(); FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.#"); System.arraycopy(r, 0, n, 0, r.length-2); String[] n = new String[r.length+1]; String[] r = results.get(i); Pair p = pairs.get(i); for (int i = 0; i < pairs.size(); i++) { if (handicaps) results.add(p.export()); for (Pair p: pairs) else } results.add(b); System.arraycopy(a, 5, b, 4, a.length-5); System.arraycopy(a, 0, b, 0, 4); String[] b = new String[a.length-1]; String[] a = p.export(); for (Pair p: pairs) { if (ximp) String[] header = headerv.toArray(new String[0]); headerv.add(_("LPs")); elsead ®dß¼˜`üϯlLç › š t _ Z Y  ñ Ü ¿ º ¹ w r X > "   Ž ‰ q = . ü Í ž J ? >  Ê • d c + ßÞ©Š\)(õ²«–•o>õ½ˆR˜M7öË™h5« „ƒZB:5ÈÛ†qU?& ýßÀ®­ "" }; : _("MPs:"), ximp ? _("IMPs") "", _("Score:"), _("Tricks"), _("By"), _("Contract"), _("EW"), _("NS"), String[] headers = new String[] { { public static void boardbyboard(List boards, TablePrinter tabular, boolean ximp, boolean withpar) } } tabular.gap(); tabular.print(headers, matrix); start += grouping; } matrix[matrix.length-1][j+1] = format.format(sums[j], tmp, field).toString(); matrix[matrix.length-2][j+1] = " "; StringBuffer tmp = new StringBuffer(); for (int j = 0; j < sums.length; j++) { matrix[matrix.length-1][0] = _("Total"); matrix[matrix.length-2][0] = " "; } } matrix[i][j+1] = " "; } else sums[j] += boards[i+start].getMPs(pairs[j].getNumber()); matrix[i][j+1] = format.format(boards[i+start].getMPs(pairs[j].getNumber()), tmp, field).toString(); if (boards[i+start].played(pairs[j].getNumber())) { StringBuffer tmp = new StringBuffer(); for (int j = 0; j < pairs.length; j++) { matrix[i][0] = boards[i+start].getNumber(); for (int i = 0; i+start < boards.length && i < grouping; i++) { float[] sums = new float[pairs.length]; while (start < boards.length) { int start = 0; String[][] matrix = new String[grouping+2][pairs.length+1]; if (0 == grouping) grouping = boards.length; headers[j+1] = pairs[j].getNumber()+" "; for (int j = 0; j < pairs.length; j++) headers[0] = _("Board"); String[] headers = new String[pairs.length+1]; FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.##"); Pair[] pairs = pairv.toArray(new Pair[0]); Board[] boards = boardv.toArray(new Board[0]); Collections.sort(pairv, new PairNumberComparer()); Collections.sort(boardv, new BoardNumberComparer()); } throw new MovementVerificationException(setsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { grouping = Integer.parseInt(setsize); try { if (null != setsize && setsize.length() >= 0) int grouping = 0; { public static void matrix(List pairv, List boardv, TablePrinter tabular, String setsize) throws MovementVerificationException } modifiedpairs = true; p.total(boards); for (Pair p: pairs) { public static void total(List pairs, List boards) } modifiedboards = true; b.parimp(); for (Board b: boards) { public static void parimp(List boards) throws ScoreException } tabular.gap(); tabular.print(headers, matrix); matrix[0][2] = format.format(usimps-themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][1] = format.format(themimps, tmp, field).toString(); tmp = new StringBuffer(); matrix[0][0] = format.format(usimps, tmp, field).toString(); tmp = new StringBuffer(); String[][] matrix = new String[1][3]; StringBuffer tmp; FieldPosition field = new FieldPosition(DecimalFormat.INTEGER_FIELD); DecimalFormat format = new DecimalFormat("0.##"); headers[2] = _("Difference"); headers[1] = _("Them IMPs"); headers[0] = _("Us IMPs");adÐi»—bÿ䟀jò ¿ ¨ k ? 0  ø Ô e ] X W å à Ä    e H C B ® © v u 9 8 $  í Á • D < 5 úÅ”dD% Û¨–wH Ð\öîéè˜|cFA@ûöÚǪ¥¤(#ØÉ™j;õêéе—fM/!øÐÏ String[] headers = new String[3]; } themimps += -res[0]; else usimps += res[0]; if (res[0] > 0) double[] res = b.sumimp(prefix, teams); for (Board b: boards) { double themimps = 0; double usimps = 0; } throw new ScoreException(teamsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { teams = Integer.parseInt(teamsize); try { if (null != teamsize && teamsize.length() >= 0) int teams = 4; { public static void teams(List boards, TablePrinter tabular, String prefix, String teamsize) throws ScoreException } modifiedboards = true; b.ximp(); for (Board b: boards) { public static void ximp(List boards) throws ScoreException } modifiedboards = true; b.matchPoint(); for (Board b: boards) { public static void matchpoint(List boards) throws ScoreException } } } new Object[] { boards[i].getNumber(), h.getNS(), h.getEW() })); MessageFormat.format(_("Board {0} was played by {1} and {2}, which I was not expecting."), throw new MovementVerificationException( if (!pairs.contains(h.getNS()+" "+h.getEW())) for (Hand h: boards[i].getHands()) // check the pairs } else { pairs.add(h.getNS()+" "+h.getEW()); for (Hand h: boards[i].getHands()) pairs.clear(); // reset the pairs if (0 == (i % size)) { for (int i = 0; i < boards.length; i++) { Set pairs = new TreeSet(); Board[] boards = boardv.toArray(new Board[0]); Collections.sort(boardv, new BoardNumberComparer()); } throw new MovementVerificationException(setsize+_(" isn't a number!")); if (Debug.debug) Debug.print(NFe); } catch (NumberFormatException NFe) { size = Integer.parseInt(setsize); try { int size = 0; if (null == setsize || setsize.length() == 0) return; b.validate(); for (Board b: boardv) { public static void verify(List boardv, String setsize) throws MovementVerificationException, BoardValidationException, HandParseException } modifiedboards = true; h.score(); if (!h.isAveraged()) for (Hand h: b.getHands()) for (Board b: boards) { public static void score(List boards) throws ScoreException, ContractParseException, HandParseException } } throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); } catch (IOException e) {} ftp.disconnect(); ftp.logout(); try { if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { ftp.disconnect(); ftp.logout(); System.err.println(_("Upload complete")); // log out if (!ftp.completePendingCommand()) throw new IOException(_("Uploading end file failed")); out.close(); out.print("End\r\n"); out = new PrintStream(ftp.storeFileStream(prefix+"E.txt")); // write end file if (!ftp.completePendingCommand()) throw new IOException(_("Uploading results failed")); System.err.println(); out.close(); doR(out, boards, session); out = new PrintStream(ftp.storeFileStream(prefix+"R.txt"));ad¼fÚ¾“mQ6ÿñÕ¸€c;ö × Ì Ä ¿ ¾ 0 +  ÿ Ä r q ? ;  É ¥ Ž q ' ÷ ö Ø Ž j T S 8 î Ï ¹ ¸ – j ûóòmhgfé䪩˜qeA Ö zya/ûÍ̪vB!ÿÈ”gfJùÕ¿XW:½£- ï¼» System.err.print(_("Uploading results")); // write boards file System.err.println(); if (!ftp.completePendingCommand()) throw new IOException(_("Uploading pairs failed")); out.close(); doP(out, pairs); out = new PrintStream(ftp.storeFileStream(prefix+"P.txt")); System.err.print(_("Uploading pair details")); // write pairs file if (!ftp.completePendingCommand()) throw new IOException(_("Uploading club details failed")); out.close(); doC(out, boards, options); PrintStream out = new PrintStream(ftp.storeFileStream(prefix+"C.txt")); // write club file String prefix = prefixb.toString(); prefixb.append(phone.replaceAll(" ", "")); prefixb.append(clubName.replaceAll(" ", "")); prefixb.append(session); prefixb.append('0'); for (int i = session.length(); i < 6; i++) StringBuffer prefixb = new StringBuffer(); // calculate file prefix String phone = options.get("phone"); String clubName = options.get("clubName"); String session = options.get("session"); // get options ftp.enterLocalPassiveMode(); ftp.setFileType(FTPClient.BINARY_FILE_TYPE); ftp.changeWorkingDirectory(ECATS_UPLOAD_DIR); ftp.login(ECATS_USERNAME, ECATS_PASSWORD); ftp.connect(ECATS_SERVER); try { FTPClient ftp = new FTPClient(); // connect System.err.println(_("Uploading scores to ECATS")); { public static void uploadToECATS(List boards, List pairs, Map options) throws ScoreException } System.err.println(_("ECATS files have been written. Email the files C.txt, P.txt, R.txt and E.txt to results@simpairs.com")); } throw new ScoreException(_("Exception occurred while trying to upload to ECATS: ")+IOe.getMessage()); if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { out.close(); out.print("End\r\n"); out = new PrintStream(new FileOutputStream(exportdir+"/E.txt")); // write end file out.close(); doR(out, boards, session); out = new PrintStream(new FileOutputStream(exportdir+"/R.txt")); // write boards file out.close(); doP(out, pairs); out = new PrintStream(new FileOutputStream(exportdir+"/P.txt")); // write pairs file out.close(); doC(out, boards, options); PrintStream out = new PrintStream(new FileOutputStream(exportdir+"/C.txt")); // write club file String session = options.get("session"); System.err.println(_("Exporting scores in ECATS format to ")+exportdir); exportdir = new File (".").getCanonicalPath(); if (null == exportdir) try { { public static void exportToECATS(List boards, List pairs, Map options, String exportdir) throws ScoreException } } } out.print("\r\n"); out.print("0"); //spare = 0 out.print("\t"); out.print("0"); //spare = 0 out.print("\t"); out.print(session); // session number again out.print("\t"); out.print('"'); } } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60");ad]¸¡/Ô½kTû µ ž p Y  ø q Z   ² ™ ” “ U P 4  ô Ú ´ š b H ë Ñ « ‘ k Q éÍÅÀpkL%ÞÁ“v<èË©ŒjMгŠm+ͰmPôµ˜|Z;æÀ¤yS7öåº case Hand.AVERAGE_PLUS: switch (b.getEWAverage()) { } out.print("50"); default: break; out.print("40"); case Hand.AVERAGE_MINUS: break; out.print("60"); case Hand.AVERAGE_PLUS: switch (b.getNSAverage()) { out.print("A"); if (b.isAveraged()) { out.print('"'); out.print("\t"); out.print(""+b.getEWMP()); // double, recalculated out.print("\t"); out.print(""+b.getNSMP()); // double, recalculated out.print("\t"); out.print("\""+b.getDeclarer()+'"'); // text, not used out.print("\t"); out.print("\""+b.getTricks()+'"'); // text, not used out.print("\t"); out.print('"'+b.getContract()+'"'); // text, not used out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print(""+(int) b.getEWScore()); out.print("\t"); out.print(""+(int) b.getNSScore()); out.print("\t"); out.print(b.getEW()); out.print("\t"); out.print(b.getNS()); out.print("\t"); out.print(b.getNumber()); // int, non zero out.print("\t"); out.print("\"\""); // section, not used == "" out.print("\t"); out.print("\"\""); // spare == "" out.print("\t"); out.print("0"); // spare == 0 out.print("\t"); for (Hand b: bd.getHands()) { for (Board bd: boards) { { private static void doR(PrintStream out, List boards, String session) } } out.print("\r\n"); out.print("\"NS\""); // for a 2 winner movement, set this to the direction they were sitting. out.print("\t"); out.print('"'+names[1]+'"'); out.print("\t"); out.print('"'+names[0]+'"'); out.print("\t"); out.print('"'+names[0]+" & "+names[1]+'"'); String[] names = p.getNames(); out.print("\t"); out.print(p.getNumber()); // pair number (int) out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); out.print("0"); // spare = 0 out.print("\t"); for (Pair p: pairs) { { private static void doP(PrintStream out, List pairs) } out.print("\r\n"); out.print('"'+options.get("event")+'"'); // event name, text (max 50 chars) out.print("\t"); out.print('"'+options.get("date")+'"'); // "dd/mm/yyyy" out.print("\t"); out.print('"'+ECATS_PROGRAM_VERSION+'"'); // program version. Important. My program? their program? this number seems to work... out.print("\t"); out.print(options.get("session")); //session #, compulsory, numeric out.print("\t"); out.print("\"false\""); //spare = false out.print("\t"); out.print('"'+options.get("email")+'"'); //email (max 50 chars) out.print("\t"); out.print('"'+options.get("fax")+'"'); //fax (max 50 chars) out.print("\t"); out.print('"'+options.get("phone")+'"'); //phone, compulsory (max 50 chars) out.print("\t"); out.print('"'+options.get("name")+'"'); //name (max 50 chars) out.print("\t"); out.print('"'+options.get("country")+'"'); //country, compulsory, spelling agreed in advance (max 50 chars) out.print("\t"); out.print('"'+options.get("county")+'"'); //county (max 50 chars)ad1Éa㺑ƒZO*äßÞˆƒDØ Ë ¨ z 9  Ý Ò ­ › ™ f E  ð Ç ž s G . é Ð ® § ¡ œ ˜ — ƒ ~ } - ( â È ¢ Š ‰ q l ' ì›=œØÓÒÑ~y3óÊ·²±TO:#ê®—Q:ì«”;$àÉÈ out.print("\t"); out.print('"'+options.get("town")+'"'); //town (max 50 chars) out.print("\t"); out.print('"'+options.get("clubName")+'"'); //club name, compulsory (max 50 chars) out.print("\t"); out.print("\"true\""); // true iff contracts were recorded out.print("\t"); out.print("0"); // #boards/round (not important) out.print("\t"); out.print(""+boards.size()); // # boards played (not important) out.print("\t"); out.print("\"false\""); // true iff 2 winner movement out.print("\t"); out.print("1"); //spare = 1 out.print("\t"); // write C.txt { private static void doC(PrintStream out, List boards, Map options) } out.close(); out.writeRecord(h.export()); for (Hand h: b.getHands()) for (Board b: boards) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writeBoards(List boards, OutputStream os) throws IOException } System.out.println(" Formats: txt html htmlfrag pdf csv"); System.out.println(" Options: --help --output=[:]file --title=title --orange --setsize=N --ximp --with-par --trickdata= --handicapdata= --with-handicaps --handicap-normalizer= --ecats-options= --print-ecats-options --mpscale= --print-mpscales --teamsize=N --teamprefix= --original-entry=<#tables>"); System.out.println(" Commands: verify score matchpoint ximp parimp total handicap localpoint results matrix boards ecats-upload scoreteams scorecards"); System.out.println("Usage: salliere [options] [commands] -- "); System.out.println("Salliere Duplicate Bridge Scorer - version "+version); .getImplementationVersion(); String version = Package.getPackage("cx.ath.matthew.salliere") { static void syntax() } out.close(); out.writeRecord(p.export()); for (Pair p: pairs) CsvWriter out = new CsvWriter(new OutputStreamWriter(os), ','); { static void writePairs(List pairs, OutputStream os) throws IOException } return pairs; } } } } pairmap.get(s).addHand(h); for (String s: ss) ss = h.getEW().split("\\."); pairmap.get(s).addHand(h); for (String s: ss) String[] ss = h.getNS().split("\\."); // probably individual } else { pairmap.get(h.getEW()).addHand(h); pairmap.get(h.getNS()).addHand(h); if (pairmap.containsKey(h.getNS())) { System.err.println("NS="+h.getNS()); for (Hand h: b.getHands()) { for (Board b: boards) { if (null != boards) { in.close(); } catch (EOFException EOFe) {} } pairmap.put(p.getNumber(), p); pairs.add(p); Pair p = new Pair(values); if (Debug.debug) Debug.print(Arrays.asList(values)); String[] values = in.getValues(); while (in.readRecord()) { try { HashMap pairmap = new HashMap(); List pairs = new Vector(); CsvReader in = new CsvReader(new InputStreamReader(is)); { static List readPairs(InputStream is, List boards) throws IOException } return new ArrayList(boards.values()); in.close(); } catch (EOFException EOFe) {} } b.addHand(new Hand(values)); } boards.put(values[0], b); b = new Board(values[0]); if (null == b) {ad¨ase`_ôó“B÷ Ö Õ “ Z V < ò Ñ ¦ s /  ã ¹ Y  ÷ ê „ ^ X W B ø å É  l _ %   ÿúùÓ‰$Þ³€<  Á®’H5(îÞÎÈÃÂ7¯ªonû辟—–‘2-~P1ãÕ¨§ Board b = boards.get(values[0]); } Debug.print(in.getCurrentRecord()+": "+Arrays.asList(values)); if (Debug.debug) { String[] values = in.getValues(); while (in.readRecord()) { try { Map boards = new HashMap(); CsvReader in = new CsvReader(new InputStreamReader(is)); { static List readBoards(InputStream is) throws IOException, BoardValidationException } } b.importTricks(s); if (null != (s = br.readLine())) String s; for (Board b: boards) { BufferedReader br = new BufferedReader(new InputStreamReader(trickdatafile)); Collections.sort(boards, new BoardNumberComparer()); { static void readTrickData(List boards, InputStream trickdatafile) throws IOException } } return points2-points1; if (Debug.debug) Debug.print(Debug.DEBUG, ob1.getNumber()+" have "+points1+" points and "+ob2.getNumber()+" have "+points2+" points."); } } points2++; points1++; if (Debug.debug) Debug.print(Debug.VERBOSE, "Draw"); } else { points2 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" win"); } else if (mp1 < mp2) { points1 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" win"); if (mp1 > mp2) { else mp2 = h.getEWMP(); || h.getNS().endsWith("."+ob2.getNumber())) mp2 = h.getNSMP(); || h.getNS().startsWith(ob2.getNumber()+".") if (h.getNS().equals(ob2.getNumber()) mp1 = h.getBoard().getTop() / 2; double mp1 = 0.0, mp2 = 0.0; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" not played, treating as average"); if (Debug.debug) Debug.print(Debug.VERBOSE, "Board: "+h.getNumber()); for (Hand h: hands2map.values()) { } } points2++; points1++; if (Debug.debug) Debug.print(Debug.VERBOSE, "Draw"); } else { points2 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" win"); } else if (mp1 < mp2) { points1 += 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob1.getNumber()+" win"); if (mp1 > mp2) { } mp2 = h.getBoard().getTop() / 2; if (Debug.debug) Debug.print(Debug.VERBOSE, ob2.getNumber()+" not played, treating as average"); } else { else mp2 = h.getEWMP(); || h.getNS().endsWith("."+ob2.getNumber())) mp2 = h.getNSMP(); || h.getNS().startsWith(ob2.getNumber()+".") if (h.getNS().equals(ob2.getNumber()) h = hands2map.remove(h.getNumber()); if (hands2map.containsKey(h.getNumber())) { else mp1 = h.getEWMP(); || h.getNS().endsWith("."+ob1.getNumber())) mp1 = h.getNSMP(); || h.getNS().startsWith(ob1.getNumber()+".") if (h.getNS().equals(ob1.getNumber()) double mp1 = 0.0, mp2 = 0.0; if (Debug.debug) Debug.print(Debug.VERBOSE, "Board: "+h.getNumber()); for (Hand h: hands1) { for (Hand h: hands2) hands2map.put(h.getNumber(), h); HashMap hands2map = new HashMap(); int points1 = 0, points2 = 0; if (Debug.debug) Debug.print(Debug.DEBUG, "Point-a-board count-back:"); and only for two-way ties. Matchpoint the matchpoints for these two pairs */ /* Only using this method here, so only works for all-play-all events without direct matches if (Debug.debug) Debug.print(Debug.INFO, "Splitting tie for "+ob1.getNumber()+" and "+ob2.getNumber()); } return 0; if (Debug.debug) Debug.print(Debug.INFO, "Can't Split tie for "+ob1.getNumber()+" and "+ob2.getNumber()+", because there are no hands");adÝkÅĦlB ëÅU8-¡ “ [   ú õ ‰ „ \ D .  ý ç Î µ ¥ ‡ g . ó ò Ú È ¦ ‹ ƒ j N ,   ö  § ‚ O 5 麣Šs\E.þη mMî×À©’b2ý÷ò·¥¡œ›š$Ú•‰=ìr5*óÇjbF&þÝÜ for (String n: names) { String[] names = p.getNames(); double handicap = 0.0; for (Pair p: pairs) { } throw new ScoreException(_("Failure in reading handicap file: ")+IOe.getMessage()); if (Debug.debug) Debug.print(IOe); } catch (IOException IOe) { in.close(); } handicaps.put(values[0], new Double(values[1])); if (values.length != 2) throw new ScoreException(_("Malformed handicap line: ")+Arrays.deepToString(values)); String[] values = in.getValues(); while (in.readRecord()) { CsvReader in = new CsvReader(new InputStreamReader(handicapfile)); try { Map pairhandicaps = new HashMap(); Map handicaps = new HashMap(); { public static Map readHandicapData(List pairs, InputStream handicapfile) throws ScoreException } } tabular.gap(); tabular.print(headers, lines.toArray(new String[0][])); } } } lines.add(line); line[8] = ex[9]; line[7] = ex[6].equals("0") ? "" : ex[6]; line[6] = ex[7].equals("0") ? "" : ex[7]; line[5] = ex[5]; line[4] = ex[4]; line[3] = ex[3]; line[2] = ex[1]; line[1] = _("EW"); line[0] = ex[0]; String[] line = new String[ex.length-1]; String[] ex = h.export(); } else if (h.getEW().equals(p.getNumber())) { lines.add(line); line[8] = ex[8]; line[7] = ex[7].equals("0") ? "" : ex[7]; line[6] = ex[6].equals("0") ? "" : ex[6]; line[5] = ex[5]; line[4] = ex[4]; line[3] = ex[3]; line[2] = ex[2]; line[1] = _("NS"); line[0] = ex[0]; String[] line = new String[ex.length-1]; String[] ex = h.export(); if (h.getNS().equals(p.getNumber())) { for (Hand h: hands) { Collections.sort(hands, new HandNSComparer()); List hands = b.getHands(); for (Board b: boards) { Vector lines = new Vector(); tabular.header(header); } header += ", "+n; for (String n: p.getNames()) { header += p.getNumber(); header = _("Pair "); else header = _("Player "); if (p.getNames().length == 1) String header; for (Pair p: pairs) { Collections.sort(boards, new BoardNumberComparer()); Collections.sort(pairs, new PairNumberComparer()); : _("MPs:")}; ximp ? _("IMPs") "", _("Score:"), _("Tricks"), _("By"), _("Contract"), _("VS"), _("Dir"), _("Board"), String[] headers = new String[] { { public static void scorecards(List pairs, List boards, TablePrinter tabular, boolean ximp) } } tabular.gap(); tabular.print(headers, lines.toArray(new String[0][])); tabular.header(_("Board: ")+b.getNumber()); else tabular.header(_("Board: ")+b.getNumber()+" [ "+b.getParContract()+" by "+b.getPar().getDeclarer()+" ]"); if (withpar) } lines.add(line); System.arraycopy(ex, 1, line, 0, line.length); String[] line = new String[ex.length-1]; String[] ex = h.export(); for (Hand h: hands) { Collections.sort(hands, new HandNSComparer()); List hands = b.getHands(); Vector lines = new Vector(); for (Board b: boards) { Collections.sort(boards, new BoardNumberComparer());salliere-0.10/README0000644000175000017500000000665511134734605012602 0ustar mjj29mjj29Salliere Duplicate Bridge Scorer -------------------------------- Salliere scores, matchpoints and nicely formats the boards for a duplicate pairs evening. The command line is a list of commands followed by two comma-separated files on which to operate. The syntax is: salliere [options] [commands] -- The boards file must contain lines with at least board number, NS pair number, EW pair number, Contract, Declarer and either tricks or the contract must include whether it made (=) went down (-tricks) or made over tricks (+tricks). The names file must list at least pair number followed by two comma separated names. Board numbers are generally just integers, but may have section numbering and may have the vulnerability manually overridden. The syntax for a board number is: [section:]number[;options], where options are comma separated key=value pairs. The only valid key at the moment is 'vul', which has the possible options 'none', 'ew', 'ns' or 'all. The following are all valid board numbers: 4 - board 4 A:12 - board 12 in section A 16;vul=ns - board 16 with the vulnerability set to be NS vulnerable, EW non-vulnerable. C:25;vul=all - board 25 from section C with all vulnerable The commands will add tricks, scores and matchpoint/cross-imp columns to the boards file and total matchpoints/cross-imps, percentages and local/orange points to the names file as appropriate. Assigned/Adjusted scores and matchpoints can be entered into the file by prefixing them with an exclamation mark (!). Scores marked as such will override the calculated scores/MPs for the board. Averages are supported by putting av=/av+/av- in the appropriate score fields. Split scores are also supported. By default the commands which print results will do so as ascii to stdout. This can be changed with the --output=format:file option. Formats are either pdf, html or txt and file is the path to a file or - for stdout. The commands which format the output require the extra fields to be added either by hand or with the appropriate commands so they can be printed. The commands are as follows: verify Checks all the boards look sane; can be used with the --setsize option to check the movement. score Calculates tricks and score for each contract matchpoint Calculates match points for each hand ximp Calculates the cross-IMPs for each hand total Calculates the total match points for each pair localpoint Calculates local or orange points for each pair results Prints all the pairs in order with their total match points, percentages and local/orange points as appropriate matrix Prints a matrix of match points gained on each board by each pair boards Prints out each board with pairs, contract, results and match points Here are the possible options: --help Prints the help text --orange Prints "OP" rather than "LP" --ximp Prints "IMP" rather than "MP" and removes percentages from the output --title=title Changes the title on the output --setsize=N Check the movement based on sets of size N --output=format:file Changes the output format and file. Possible formats are pdf, html or txt. A file of ’-’ corresponds to stdout. salliere-0.10/INSTALL0000644000175000017500000000131111164770312012731 0ustar mjj29mjj29Installation Instructions ------------------------- To build salliere you will need a 1.5 compatible Java compiler with at least 1.4 compatible java libraries, libcsv-java (http://sourceforge.net/projects/javacsv/), libmatthew-debug-java (http://www.matthew.ath.cx/projects/java/) and libitext-java (v2 or higher) (http://www.lowagie.com/iText/) To build: make all To install: make install Both of these can be modified by setting variables. See the Makefile for more details, but the most likely ones to be changed are: PREFIX = install prefix JAVAC = Java compiler JAVA = Java VM CLASSPATH = path to libcsv-java, libmatthew-debug-java and libitext DEBUG = enable to enable debugging salliere-0.10/COPYING0000644000175000017500000004310211134734605012741 0ustar mjj29mjj29 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. salliere-0.10/changelog0000644000175000017500000000540511327150724013562 0ustar mjj29mjj29Version 0.10: * Fix Neuberging boards which weren't played as many times * Fix NPE with nonexistent pairs * Fix Individual scorecards * Fix Local-pointing with everyone getting points * Make PDF output tables bigger * Fix ECATS for individuals Version 0.9: * Rewrite everything with Java generics to remove all the warnings * Add split-tie procedures (only works for 2-way split-tie in all-play-all pairs or individual events) * Add different master point scales, now copes with: - club/district/county/regional/national scales - 12+ boards not just 18-35 - quali-final scales Version 0.8: * Fix LP allocation with odd number of pairs * Add personal score card generation * Fix MP calculations with AV-/+ Version 0.7.1: * Patch to build with itext 2.x Version 0.7: * Support any number of names (currently only in cmd line). Supersedes individual support * Add leaderboard binary for creating leaderboard/results pages * Add html-fragment output * Add csv output * Add teams of (4 or 8) scoring * Update manual page Version 0.6: * Add handicap support * Add ECATS upload support Version 0.5.2: * Fix translation keys * add ecl2salliere script Version 0.5.1: * Move installation directories around, only install into $PREFIX/share/salliere/ Version 0.5: * Support XIMP as well as Matchpointing * Support for individuals (currently only in cmd line) * Support for imping against par * Correct masterpoint awards * Open all file choosers in dir of last file operation * Fix display of redoubled contracts Version 0.4: * Support averages * Support assigned/ajusted/split scores * forcing score supported in GSalliere Version 0.3: * Support b33r card * board ordering knows about sections and vulnerabilities * --setsize parameter to check sets of n boards per round for matching pair numbers * output hands within boards sorted by NS pair number (Suggested by Carrie Oliver ) * gsalliere graphical frontend * get version from jar * add itext to INSTALL info * don't write files when they weren't modified * check that only NSEW can be declarer * don't add class-path on debug when it's disabled * output a space not a 0 in the matrix when a pair didn't play that board (Suggested by Ralph Owen ) * Output to file and output in HTML and PDF formats. * Calculate LP/OPs * Support section numbering for boards * Support vulnerability overriding * Support passouts * Pass through averages without scoring * Assorted bug fixes Version 0.1: * Initial release of salliere salliere-0.10/todo0000644000175000017500000000033611134734605012600 0ustar mjj29mjj29 * support ignoring boards from a flag, for parimping * Support scaling for split boards * check movements * Support fines * gsalliere - save button - disable menu entries and save button when they can't be used salliere-0.10/salliere.sh0000644000175000017500000000016311134734605014042 0ustar mjj29mjj29#!/bin/sh -- JAVA=%JAVA% VERSION=%VERSION% JARPATH=%JARPATH% exec $JAVA -jar $JARPATH/salliere-$VERSION.jar "$@" salliere-0.10/salliere.sgml0000644000175000017500000002670511155041135014374 0ustar mjj29mjj29 manpage.1'. You may view the manual page with: `docbook-to-man manpage.sgml | nroff -man | less'. A typical entry in a Makefile or Makefile.am is: manpage.1: manpage.sgml docbook-to-man $< > $@ The docbook-to-man binary is found in the docbook-to-man package. Please remember that if you create the nroff version in one of the debian/rules file targets (such as build), you will need to include docbook-to-man in your Build-Depends control field. --> Matthew"> Johnson"> October 20, 2007"> 1"> <debian@matthew.ath.cx>"> SALLIERE"> Debian"> GNU"> GPL"> ]>
&dhemail;
&dhfirstname; &dhsurname; 2007 &dhusername; &dhdate;
&dhucpackage; &dhsection; &dhpackage; Duplicate Bridge Scorer &dhpackage; -- boards.csv names.csv DESCRIPTION This manual page documents briefly the &dhpackage; command. &dhpackage; scores, matchpoints and nicely formats the boards for a duplicate pairs evening. The command line is a list of commands followed by two comma-separated files on which to operate. The boards file must contain lines with at least board number, NS pair number, EW pair number, Contract, Declarer and either tricks or the contract must include whether it made (=) went down (-tricks) or made over tricks (+tricks). The names file must list at least pair number followed by two comma separated names. The commands will add tricks, scores and matchpoint columns to the boards file and total matchpoints, percentages and local/orange points to the names file as appropriate. By default the commands which print results will do so as ascii to stdout. This can be changed with the --output=format:file option. Formats are either pdf, html or txt and file is the path to a file or - for stdout. The commands which format the output require the extra fields to be added either by hand or with the appropriate commands so they can be printed. COMMANDS Here are a list of the available commands and what they do: verify Checks all the boards look sane; can be used with the --setsize option to check the movement score Calculates tricks and score for each contract matchpoint Calculates match points for each hand ximp Calculates cross-imps for each hand parimp Calculates imps vs par for each hand total Calculates the total match points for each pair handicap Calculates the result after applying handicaps for each player localpoint Calculates local or orange points for each pair results Prints all the pairs in order with their total match points, percentages and local/orange points as appropriate matrix Prints a matrix of match points gained on each board by each pair boards Prints out each board with pairs, contract, results and match points ecats-upload Upload results to ecats bridge website scoreteams Prints out the results of the boards as a team of 4 or team of 8 match OPTIONS Here are a list of the available options and what they do: --help Prints the help text --setsize=N Check the movement based on sets of size N. Also used when printing the matrix to batch the results --orange Prints "OP" rather than "LP" --ximp Adjusts output for IMPs rather than matchpoints --title=title Changes the title on the output --output=format:file Changes the output format and file. Possible formats are pdf, html, htmlfrag, csv or txt. A file of '-' corresponds to stdout. --with-par Prints the par result along with the boards --trickdata=file The tricks which can be made on each board for calculating par --handcapdata Current handicaps for individuals --with-handicaps Prints the handicaps with each pair --handcap-normalizer When handicapping, center around this number as par --teamsize=N Number of players in a team (4 or 8) for overall team scoring --teamprefix=prefix The prefix on each pair number to identify which team they are on (eg CU if the pairs are named CU1, CU2, ...) --ecats-options=key:value,key2:value2,... Options used to send scores to ecats. ECATS OPTIONS Here are a list of the available options to ecats and what they do. clubNamename of club (required) sessionECATS session number (required) phonecontact phone number (required) countryclub country (required) namecontact name faxcontact fax number emailcontact email townclub town countyclub county dateevent date eventevent name AUTHOR This manual page was written by &dhusername; &dhemail;. Permission is granted to copy, distribute and/or modify this document under the terms of the &gnu; General Public License, Version 2 as published by the Free Software Foundation. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL.
salliere-0.10/Manifest.txt.in0000644000175000017500000000017411134734605014624 0ustar mjj29mjj29Name: cx/ath/matthew/salliere Implementation-Title: Salliere Duplicate Bridge Scorer Implementation-Vendor: Matthew Johnson salliere-0.10/gsalliere.sh0000644000175000017500000000016411134734605014212 0ustar mjj29mjj29#!/bin/sh -- JAVA=%JAVA% VERSION=%VERSION% JARPATH=%JARPATH% exec $JAVA -jar $JARPATH/gsalliere-$VERSION.jar "$@" salliere-0.10/gsalliere.sgml0000644000175000017500000000734211134734605014547 0ustar mjj29mjj29 manpage.1'. You may view the manual page with: `docbook-to-man manpage.sgml | nroff -man | less'. A typical entry in a Makefile or Makefile.am is: manpage.1: manpage.sgml docbook-to-man $< > $@ The docbook-to-man binary is found in the docbook-to-man package. Please remember that if you create the nroff version in one of the debian/rules file targets (such as build), you will need to include docbook-to-man in your Build-Depends control field. --> Matthew"> Johnson"> April 28, 2007"> 1"> <debian@matthew.ath.cx>"> GSALLIERE"> Debian"> GNU"> GPL"> ]>
&dhemail;
&dhfirstname; &dhsurname; 2007 &dhusername; &dhdate;
&dhucpackage; &dhsection; &dhpackage; Duplicate Bridge Scorer &dhpackage; DESCRIPTION This manual page documents briefly the &dhpackage; command. &dhpackage; scores, matchpoints and nicely formats the boards for a duplicate pairs evening. It is a graphical frontend to salliere(1). Board and names files may be specified on the command line or loaded once the program has started. The boards file must contain lines with at least board number, NS pair number, EW pair number, Contract, Declarer and either tricks or the contract must include whether it made (=) went down (-tricks) or made over tricks (+tricks). The names file must list at least pair number followed by two comma separated names. AUTHOR This manual page was written by &dhusername; &dhemail;. Permission is granted to copy, distribute and/or modify this document under the terms of the &gnu; General Public License, Version 2 as published by the Free Software Foundation. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL.
salliere-0.10/translations/0000755000175000017500000000000011306575224014430 5ustar mjj29mjj29salliere-0.10/translations/en_GB.po0000644000175000017500000003031111327150635015736 0ustar mjj29mjj29#java-format msgid "%age" msgstr "%age" msgid "Allocating local points" msgstr "Allocating local points" msgid "Bad Command: " msgstr "Bad Command: " msgid "Board" msgstr "Board" msgid "Board: " msgstr "Board: " msgid "Board {0} has been played by pair {1} twice." msgstr "Board {0} has been played by pair {1} twice." msgid "Board {0} was played by {1} and {2}, which I was not expecting." msgstr "Board {0} was played by {1} and {2}, which I was not expecting." msgid "Board-by-boards" msgstr "Board-by-boards" msgid " (board might be number {0})" msgstr " (board might be number {0})" msgid "Boards" msgstr "Boards" msgid " by " msgstr " by " msgid "By" msgstr "By" msgid "Calculated {0} LPs for pair {1} but data says {2}." msgstr "Calculated {0} LPs for pair {1} but data says {2}." msgid "Calculated {0} MPs for EW, but hand says: {1}" msgstr "Calculated {0} MPs for EW, but hand says: {1}" msgid "Calculated {0} MPs for NS, but hand says: {1}" msgstr "Calculated {0} MPs for NS, but hand says: {1}" msgid "Calculated score as {0} for EW but hand says {1}." msgstr "Calculated score as {0} for EW but hand says {1}." msgid "Calculated score as {0} for NS but hand says {1}." msgstr "Calculated score as {0} for NS but hand says {1}." msgid "Calculated tricks as {0} but hand says {1}." msgstr "Calculated tricks as {0} but hand says {1}." msgid "Calculate local points for the pairs" msgstr "Calculate local points for the pairs" msgid "Calculating total matchpoints and percentages" msgstr "Calculating total matchpoints and percentages" msgid "Cannot re-re-double contracts!" msgstr "Cannot re-re-double contracts!" msgid "Cannot take {0} tricks!" msgstr "Cannot take {0} tricks!" msgid "Club Name" msgstr "Club Name" msgid "Contact Email" msgstr "Contact Email" msgid "Contact Fax Number" msgstr "Contact Fax Number" msgid "Contact Name" msgstr "Contact Name" msgid "Contact Phone Number" msgstr "Contact Phone Number" msgid "Contract" msgstr "Contract" msgid "Could not find master point scale: " msgstr "Could not find master point scale: " msgid "Country" msgstr "Country" msgid "County" msgstr "County" msgid "Cross-IMP the boards" msgstr "Cross-IMP the boards" msgid "Date" msgstr "Date" msgid "Difference" msgstr "Difference" msgid "Dir" msgstr "Dir" msgid "Directory to export to" msgstr "Directory to export to" msgid "E" msgstr "E" msgid "ECATS" msgstr "ECATS" msgid "ECATS files have been written. Email the files C.txt, P.txt, R.txt and E.txt to results@simpairs.com" msgstr "ECATS files have been written. Email the files C.txt, P.txt, R.txt and E.txt to results@simpairs.com" msgid "Edit Board " msgstr "Edit Board " msgid "ERR0R" msgstr "ERR0R" msgid "Error" msgstr "Error" msgid "Error: " msgstr "Error: " msgid "Error: unknown option " msgstr "Error: unknown option " msgid "Event" msgstr "Event" msgid "EW" msgstr "EW" msgid "Exception occurred while trying to upload to ECATS: " msgstr "Exception occurred while trying to upload to ECATS: " msgid "Export" msgstr "Export" msgid "Export in ECATS format" msgstr "Export in ECATS format" msgid "Exporting results" msgstr "Exporting results" msgid "Exporting results for ECATS" msgstr "Exporting results for ECATS" msgid "Exporting scores in ECATS format to " msgstr "Exporting scores in ECATS format to " msgid "Export Results" msgstr "Export Results" msgid "Export the Results" msgstr "Export the Results" msgid "Export to ECATS format" msgstr "Export to ECATS format" msgid "Failed to parse contract on board {0}: {1}" msgstr "Failed to parse contract on board {0}: {1}" msgid "Failure in reading handicap file: " msgstr "Failure in reading handicap file: " msgid "Fields" msgstr "Fields" msgid "File" msgstr "File" msgid " (forced)" msgstr " (forced)" msgid "GSalliere - Duplicate Bridge Scoring" msgstr "GSalliere - Duplicate Bridge Scoring" msgid "Has options to load and save score files and export results" msgstr "Has options to load and save score files and export results" msgid "h'cap" msgstr "h'cap" msgid "HTML" msgstr "HTML" msgid "IMPing boards against par" msgstr "IMPing boards against par" msgid "IMP-Par" msgstr "IMP-Par" msgid "IMPs" msgstr "IMPs" msgid "IMP the boards against par" msgstr "IMP the boards against par" msgid "Insufficient fields. I cannot parse a board without at least board number, pair numbers and contract" msgstr "Insufficient fields. I cannot parse a board without at least board number, pair numbers and contract" msgid "Invalid Average: " msgstr "Invalid Average: " msgid "Invalid Hand Number: " msgstr "Invalid Hand Number: " msgid "Invalid Number of Match Points: " msgstr "Invalid Number of Match Points: " msgid "Invalid Number of Tricks: " msgstr "Invalid Number of Tricks: " msgid "Invalid Score: " msgstr "Invalid Score: " msgid " isn't a number!" msgstr " isn't a number!" msgid "LeaderBoard failed: " msgstr "LeaderBoard failed: " msgid "Loaded Boards from " msgstr "Loaded Boards from " msgid "Loaded Names from " msgstr "Loaded Names from " msgid "Loaded Tricks from " msgstr "Loaded Tricks from " msgid "Loading Boards..." msgstr "Loading Boards..." msgid "Loading Boards from " msgstr "Loading Boards from " msgid "Loading Names..." msgstr "Loading Names..." msgid "Loading Names from " msgstr "Loading Names from " msgid "Loading Tricks..." msgstr "Loading Tricks..." msgid "Loading Tricks from " msgstr "Loading Tricks from " msgid "Load Names File" msgstr "Load Names File" msgid "Load Score File" msgstr "Load Score File" msgid "Load Tricks File" msgstr "Load Tricks File" msgid "Local Point" msgstr "Local Point" msgid "Local Points" msgstr "Local Points" msgid "LPs" msgstr "LPs" msgid " making " msgstr " making " msgid "Malformed handicap line: " msgstr "Malformed handicap line: " msgid "Mandatory" msgstr "Mandatory" msgid "Match Point" msgstr "Match Point" msgid "Matchpointing boards" msgstr "Matchpointing boards" msgid "Match Points" msgstr "Match Points" msgid "Matchpoint the boards" msgstr "Matchpoint the boards" msgid "MP EW" msgstr "MP EW" msgid "MP Matrix" msgstr "MP Matrix" msgid "MP NS" msgstr "MP NS" msgid "MPs" msgstr "MPs" msgid "MPs:" msgstr "MPs:" msgid "Must have at least {0} competitors to award local points in this event" msgstr "Must have at least {0} competitors to award local points in this event" msgid "Must Load Boards and Pairs before exporting results" msgstr "Must Load Boards and Pairs before exporting results" msgid "Must Load Boards and Pairs before Totalling" msgstr "Must Load Boards and Pairs before Totalling" msgid "Must Load Boards before allocating local points" msgstr "Must Load Boards before allocating local points" msgid "Must Load Boards before IMPing" msgstr "Must Load Boards before IMPing" msgid "Must Load Boards before loading trick data" msgstr "Must Load Boards before loading trick data" msgid "Must Load Boards before Matchpointing" msgstr "Must Load Boards before Matchpointing" msgid "Must Load Boards before saving them" msgstr "Must Load Boards before saving them" msgid "Must Load Boards before Scoring" msgstr "Must Load Boards before Scoring" msgid "Must Load Boards before Verifying movement" msgstr "Must Load Boards before Verifying movement" msgid "Must Load Boards before XIMPing" msgstr "Must Load Boards before XIMPing" msgid "Must Load Pairs and boards before exporting" msgstr "Must Load Pairs and boards before exporting" msgid "Must Load Pairs and boards before uploading to ECATS" msgstr "Must Load Pairs and boards before uploading to ECATS" msgid "Must Load Pairs before allocating local points" msgstr "Must Load Pairs before allocating local points" msgid "Must Load Pairs before saving them" msgstr "Must Load Pairs before saving them" msgid "Must supply a handicap file before calculating handicapped scores" msgstr "Must supply a handicap file before calculating handicapped scores" msgid "N" msgstr "N" msgid "Name" msgstr "Name" msgid "Names" msgstr "Names" msgid "No denomination specified in contract" msgstr "No denomination specified in contract" msgid "NS" msgstr "NS" msgid "Num" msgstr "Num" msgid "Number" msgstr "Number" msgid "On board {0} declarer should be one of NSEW, it is actually {1}." msgstr "On board {0} declarer should be one of NSEW, it is actually {1}." msgid "OPs" msgstr "OPs" msgid "Optional" msgstr "Optional" msgid "Orange Points" msgstr "Orange Points" msgid "Pair" msgstr "Pair" msgid "Pair " msgstr "Pair " msgid "Pairs" msgstr "Pairs" msgid "PDF" msgstr "PDF" msgid "Percentage" msgstr "Percentage" msgid "Played" msgstr "Played" msgid "Player " msgstr "Player " msgid "Points" msgstr "Points" msgid "Problem exporting to ECATS: " msgstr "Problem exporting to ECATS: " msgid "Problem loading boards file: " msgstr "Problem loading boards file: " msgid "Problem loading names file: " msgstr "Problem loading names file: " msgid "Problem saving boards file: " msgstr "Problem saving boards file: " msgid "Problem saving names file: " msgstr "Problem saving names file: " msgid "Problem validating boards: " msgstr "Problem validating boards: " msgid "Problem while entering score: " msgstr "Problem while entering score: " msgid "Problem while exporting: " msgstr "Problem while exporting: " msgid "Problem while performing action: " msgstr "Problem while performing action: " msgid "Quit" msgstr "Quit" msgid "Required ECATS option not found: " msgstr "Required ECATS option not found: " msgid "Results" msgstr "Results" msgid "S" msgstr "S" msgid "Salliere Duplicate Bridge Scorer: Results" msgstr "Salliere Duplicate Bridge Scorer: Results" msgid "Salliere failed to compute results: " msgstr "Salliere failed to compute results: " msgid "Save" msgstr "Save" msgid "Save both files" msgstr "Save both files" msgid "Saved Boards to " msgstr "Saved Boards to " msgid "Saved Names to " msgstr "Saved Names to " msgid "Save Names File" msgstr "Save Names File" msgid "Save Score File" msgstr "Save Score File" msgid "Saving Boards" msgstr "Saving Boards" msgid "Saving Boards to " msgstr "Saving Boards to " msgid "Saving Names" msgstr "Saving Names" msgid "Saving Names to " msgstr "Saving Names to " msgid "Score" msgstr "Score" msgid "Score:" msgstr "Score:" msgid "Score EW" msgstr "Score EW" msgid "Score NS" msgstr "Score NS" msgid "Score the contracts" msgstr "Score the contracts" msgid "Scoring boards" msgstr "Scoring boards" msgid "Session" msgstr "Session" msgid "Set Size:" msgstr "Set Size:" msgid "Show Par" msgstr "Show Par" msgid "Symbol: {0} not allowed in contract" msgstr "Symbol: {0} not allowed in contract" msgid "Text" msgstr "Text" msgid "Them IMPs" msgstr "Them IMPs" msgid "There was a problem during the execution of GSalliere: " msgstr "There was a problem during the execution of GSalliere: " msgid "This Hand is number {0} but this is board {1}." msgstr "This Hand is number {0} but this is board {1}." msgid "Title: " msgstr "Title: " msgid " to EW " msgstr " to EW " msgid " to EW." msgstr " to EW." msgid " to NS " msgstr " to NS " msgid "Total" msgstr "Total" msgid "Total the match points for the pairs" msgstr "Total the match points for the pairs" msgid "Town" msgstr "Town" msgid " tricks. " msgstr " tricks. " msgid "Tricks" msgstr "Tricks" msgid "Unknown format: " msgstr "Unknown format: " msgid "Upload complete" msgstr "Upload complete" msgid "Uploading club details failed" msgstr "Uploading club details failed" msgid "Uploading end file failed" msgstr "Uploading end file failed" msgid "Uploading pair details" msgstr "Uploading pair details" msgid "Uploading pairs failed" msgstr "Uploading pairs failed" msgid "Uploading results" msgstr "Uploading results" msgid "Uploading results failed" msgstr "Uploading results failed" msgid "Uploading results to ECATS" msgstr "Uploading results to ECATS" msgid "Uploading scores to ECATS" msgstr "Uploading scores to ECATS" msgid "Upload Results to ECATS" msgstr "Upload Results to ECATS" msgid "Upload to ECATS" msgstr "Upload to ECATS" msgid "Us IMPs" msgstr "Us IMPs" msgid "Validate" msgstr "Validate" msgid "Validate the movement" msgstr "Validate the movement" msgid "Value must be between 1 & 7" msgstr "Value must be between 1 & 7" msgid "Verifying Movement" msgstr "Verifying Movement" msgid " vs " msgstr " vs " msgid "VS" msgstr "VS" msgid "W" msgstr "W" msgid "XIMP" msgstr "XIMP" msgid "XIMPing boards" msgstr "XIMPing boards" msgid "You must specify at least one names file" msgstr "You must specify at least one names file" msgid "You must specify boards.csv and names.csv" msgstr "You must specify boards.csv and names.csv" salliere-0.10/ecl2salliere.sh0000644000175000017500000000240511134734605014611 0ustar mjj29mjj29#!/bin/bash -- INPUT=$1 SCORES=$2 NAMES=$3 if [ -z "$NAMES" ]; then echo "Usage: ecl2salliere " exit 1 fi echo -n > $NAMES cat $INPUT | ( while read i; do if [ -z "$i" ] || [ "$i" = ",,,,,,," ]; then continue elif [ "${i:0:1}" = '"' ]; then TEAM=${i:1:1} echo "Starting team $TEAM" 1>&2 board=0 names=1 elif [ "1" = "$names" ]; then c=0 echo $i | awk -F, '{print "CU'${TEAM}$(( ++c ))',"$1","$2"\nCU'${TEAM}$(( ++c ))',"$3","$4"\nCU'${TEAM}$(( ++c ))',"$5","$6"\nCU'${TEAM}$(( ++c ))',"$7","$8}' >> $NAMES names=0 elif echo $i | grep '^[EWNS,]*$' >/dev/null; then dir[1]=`echo $i | cut -d, -f2` dir[2]=`echo $i | cut -d, -f4` dir[3]=`echo $i | cut -d, -f6` dir[4]=`echo $i | cut -d, -f8` else (( board++ )) for (( j = 1; j <= 4; j++ )); do if [ "NS" = "${dir[$j]}" ]; then echo -n $board,CU$TEAM$j,OPEW,,,, echo $i | awk -F, '{print "!"$'$(( $j * 2 - 1 ))'",!"$'$(( $j * 2 ))'}' else echo -n $board,OPNS,CU$TEAM$j,,,, echo $i | awk -F, '{print "!"$'$(( $j * 2 ))'",!"$'$(( $j * 2 - 1 ))'}' fi done fi done ) > $SCORES sed -i 's/,!,/,,/g;s/!$//g' $SCORES salliere-0.10/leaderboard.sh0000644000175000017500000000016611134734605014511 0ustar mjj29mjj29#!/bin/sh -- JAVA=%JAVA% VERSION=%VERSION% JARPATH=%JARPATH% exec $JAVA -jar $JARPATH/leaderboard-$VERSION.jar "$@" salliere-0.10/leaderboard.sgml0000644000175000017500000000734211134734605015044 0ustar mjj29mjj29 manpage.1'. You may view the manual page with: `docbook-to-man manpage.sgml | nroff -man | less'. A typical entry in a Makefile or Makefile.am is: manpage.1: manpage.sgml docbook-to-man $< > $@ The docbook-to-man binary is found in the docbook-to-man package. Please remember that if you create the nroff version in one of the debian/rules file targets (such as build), you will need to include docbook-to-man in your Build-Depends control field. --> Matthew"> Johnson"> April 28, 2007"> 1"> <debian@matthew.ath.cx>"> GSALLIERE"> Debian"> GNU"> GPL"> ]>
&dhemail;
&dhfirstname; &dhsurname; 2007 &dhusername; &dhdate;
&dhucpackage; &dhsection; &dhpackage; Duplicate Bridge Scorer &dhpackage; DESCRIPTION This manual page documents briefly the &dhpackage; command. &dhpackage; scores, matchpoints and nicely formats the boards for a duplicate pairs evening. It is a graphical frontend to salliere(1). Board and names files may be specified on the command line or loaded once the program has started. The boards file must contain lines with at least board number, NS pair number, EW pair number, Contract, Declarer and either tricks or the contract must include whether it made (=) went down (-tricks) or made over tricks (+tricks). The names file must list at least pair number followed by two comma separated names. AUTHOR This manual page was written by &dhusername; &dhemail;. Permission is granted to copy, distribute and/or modify this document under the terms of the &gnu; General Public License, Version 2 as published by the Free Software Foundation. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL.