From 8b66c7432a0f853c616eb26bb145d70645e0435e Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Thu, 24 May 2012 13:03:33 +0200 Subject: [PATCH 01/32] Change styles for globalNavigationPanels set background image icon to element to make the icon clickable --- java/com.sap.sailing.gwt.ui/RaceBoard.css | 46 +++++++++++++---------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/RaceBoard.css b/java/com.sap.sailing.gwt.ui/RaceBoard.css index ff15fdeede2..2094815c995 100644 --- a/java/com.sap.sailing.gwt.ui/RaceBoard.css +++ b/java/com.sap.sailing.gwt.ui/RaceBoard.css @@ -111,34 +111,42 @@ input.opencoloumn { right:0; } -.globalNavigation-home { - background: url(images/globalNavigation-home_bg.png) 5px center no-repeat #7c7b7c; - border-radius: 0px 0px 4px 4px; - -moz-border-radius: 0px 0px 4px 4px; - -webkit-border-radius: 0px 0px 4px 4px; - margin: 0 10px 0 0; - padding: 5px 6px 5px 25px; - float: left; +.globalNavigation-home { + border-radius: 0px 0px 4px 4px; + -moz-border-radius: 0px 0px 4px 4px; + -webkit-border-radius: 0px 0px 4px 4px; + margin: 0 10px 0 0; + float: left; } .globalNavigation-home a{ - color: #fff; - text-decoration: none; + color: #fff; + text-decoration: none; + display: block; + background: url(images/globalNavigation-home_bg.png) 5px center no-repeat #7c7b7c; + padding: 5px 6px 5px 25px; + border-radius: 0px 0px 4px 4px; + -moz-border-radius: 0px 0px 4px 4px; + -webkit-border-radius: 0px 0px 4px 4px; } .globalNavigation-leaderBoard { - background: url(images/globalNavigation-leaderBoard_bg.png) 5px center no-repeat #7c7b7c; - border-radius: 0px 0px 4px 4px; - -moz-border-radius: 0px 0px 4px 4px; - -webkit-border-radius: 0px 0px 4px 4px; - padding: 5px 6px 5px 25px; - margin: 0 10px 0 0; - float: left; + border-radius: 0px 0px 4px 4px; + -moz-border-radius: 0px 0px 4px 4px; + -webkit-border-radius: 0px 0px 4px 4px; + margin: 0 5px 0 0; + float: left; } .globalNavigation-leaderBoard a { - color: #fff; - text-decoration: none; + color: #fff; + text-decoration: none; + display: block; + background: url(images/globalNavigation-leaderBoard_bg.png) 5px center no-repeat #7c7b7c; + border-radius: 0px 0px 4px 4px; + -moz-border-radius: 0px 0px 4px 4px; + -webkit-border-radius: 0px 0px 4px 4px; + padding: 5px 6px 5px 25px; } .globalNavigation-leaderBoardGroup { From ab32b2d3073f053955f6cd9fbbbe39624adcf076 Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Thu, 24 May 2012 13:44:25 +0200 Subject: [PATCH 02/32] =?UTF-8?q?Put=20titleLabel=20in=20a=20titleLabelWra?= =?UTF-8?q?pper=20it=C2=B4s=20important=20that=20the=20background=20image?= =?UTF-8?q?=20grows=20with=20the=20titleLabel=20text.=20To=20make=20that?= =?UTF-8?q?=20possible,=20the=20titleLabel=20needs=20a=20wrapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sap/sailing/gwt/ui/client/LogoAndTitlePanel.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LogoAndTitlePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LogoAndTitlePanel.java index 61dcb4b0b20..6df3aab5d9c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LogoAndTitlePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/LogoAndTitlePanel.java @@ -22,9 +22,13 @@ public class LogoAndTitlePanel extends FlowPanel { sailingAnalyticsLabel.addStyleName("sailingAnalyticsLabel boldLabel"); this.add(labelPanel); + FlowPanel titleLabelWrapper = new FlowPanel(); + titleLabelWrapper.addStyleName("titleLabelWrapper"); titleLabel = new Label(title); titleLabel.addStyleName("titleLabel"); - this.add(titleLabel); + titleLabelWrapper.add(titleLabel); + this.add(titleLabelWrapper); + } } From cc08b1bf56735f3facfc0b960cae099f0828b3a1 Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Thu, 24 May 2012 19:18:54 +0200 Subject: [PATCH 03/32] Add styles for titleLabelWrapper && titleLabel --- .../com.sap.sailing.gwt.ui/CommonControls.css | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/CommonControls.css b/java/com.sap.sailing.gwt.ui/CommonControls.css index 4871caebbf4..b45c83d2c72 100644 --- a/java/com.sap.sailing.gwt.ui/CommonControls.css +++ b/java/com.sap.sailing.gwt.ui/CommonControls.css @@ -143,15 +143,23 @@ color: #fff; } -.titleLabel { +.titleLabelWrapper { position: absolute; - width: 400px; - text-align: right; - font-family: 'UbuntuMedium', Arial, Verdana, sans-serif; - font-size: 16px; - color: #fff; - right: 5px; - top: 41px; + min-width: 400px; + text-align: right; + height: 68px; + right: 0; + top: 0; + font-family: 'UbuntuMedium', Arial, Verdana, sans-serif; + font-size: 16px; + color: #fff; + //background: url(images/titleLabelWrapper.png) right center no-repeat; +} + +.titleLabel { + background: url(images/titleLabelInner.png) left center no-repeat; + height: 68px; + padding: 0 0 0 130px; } @@ -296,9 +304,9 @@ position: fixed; width: 100%; top: 0; - background-image: url(images/header_bg_modern_eventname.png), url(images/white_gradient_header.png), url(images/header_bg_modern.png); - background-position: right top, center top, 0 0; - background-repeat: no-repeat, no-repeat, repeat-x; + background-image: url(images/white_gradient_header.png), url(images/header_bg_modern.png); + background-position: center top, 0 0; + background-repeat: no-repeat, repeat-x; box-shadow: 0 0 20px #858585; -moz-box-shadow: 0 0 20px #858585; -webkit-box-shadow: 0 0 20px #858585; From f2fa77f244fe6bab3d1c064bc6648100273b07e7 Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Thu, 24 May 2012 19:20:34 +0200 Subject: [PATCH 04/32] Add graphics for titleLabel --- .../images/titleLabelInner.png | Bin 0 -> 2745 bytes .../images/titleLabelWrapper.png | Bin 0 -> 3037 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 java/com.sap.sailing.gwt.ui/images/titleLabelInner.png create mode 100644 java/com.sap.sailing.gwt.ui/images/titleLabelWrapper.png diff --git a/java/com.sap.sailing.gwt.ui/images/titleLabelInner.png b/java/com.sap.sailing.gwt.ui/images/titleLabelInner.png new file mode 100644 index 0000000000000000000000000000000000000000..04c78e98c3cdf11eb82808a52717b0ff20ca66f3 GIT binary patch literal 2745 zcmb7GdstKT8$aO0g@Pjq-B28(Bm;J1?8?Bg3!!oe2>B(q$qu-17j|)zn*%A$n39Bm zF6#NE&;^k)K}0Z6Mg~Dizh)qpAQ`$~EN&?Xor78Z(bMz%&a>y7@Ap0L`*}Z~_xpao zXKzJCggQB59034u3VWFs4FL89(3ppGfbP!?#+E`4w2B|Eijk$MG(rUka740wAT~@Q zOb4Suq3BTNEie!OR_znV#;fAPcQaFE61))h!D}UQC>j6)gSB#DY6hsn?gP`sQZ~-o zbRCBki`ck50pY}OITze7emP44#$-jrre;-qBLeSPw+=BXvW6vSE=Mo0zsqE;5GhunIfG)VlWsm2AS*!dH5+0 zNmW9vpH%7f6oCgSQx#&lN-UFNVMO6RnOeohK}?@WkjTTs{{)sQ|0onxGJ;kpCy?+& zf2Y9kn zwFH!^!gy?)S}hha`Ti6dl_3y7^&|1PBuKk}&L?p={uB?GDVIm#JjR{W3Y08$-pu7%of|OJT!ycy*qL<$((EK~N-6$Rya6@-oH$z<@}i zL(M~@5NTv0l};kjxg?5!6haT6Lk0#PV*eyo^naI(05KuJjq$fed1`{X4<7#6_R!?d zjRQ)d-J*cD#d~JKD*)gy5ys=hYWsc}*!#BotH75w|GsF~Yo(t=eKuR*dRhB%OZK>eQl>U~IJeJ(gx!vacv@6_D~~Ar{b~5Wo&(n~fFLTaEzA%MHd21xOBnD!?M_QX=xT zMisDbnpLtrrN75qrHcrzIWaN(S!nTpS?i7k=(6&JD9F3e0H#G&zALl@e^7`GDMojk zV$q0}WHLP2-Vt}{sAUs>+g@#mtX{h}HYXTPFz5HR(Yb?OLg)LEhZY1S*~u=DwSEiZ z8=%a(LHUhGm))_LIpJQO=P{J1Ch8>y?=_6(8#hz>UeEFTZLfEs`|skNoxBi@-hDgU z{N@#n@9a@D<=Xpb{xhC({fy8PT zhwtX-plu8b{&pgidxj$7QtiM7>e;`a(Jxl+-@$ljcK6!dlaJgsMPLuJZ^w~Ge{ zvM63XyY5b@U11_`Bunq!bLgu=WiXREP@Qqlp3F7pba9Oyx>+9IV7uDmIWrGVjvQZR zK|*Wji;oaVrcP>wsiLW@?)kn)o1-VQ=~+c=-C)0bc@-}1nlwa{=c%P!i${3UTgTmT zgNhq|-Xm8H)t%~lc=NZ}sE!l-SFR*S&N-J%9>gzh|5Dy?nF<`?-axj7wI}!5zBo1I z^URlcmpilvSAEm(FY31(pP6Q1l?~TqKHRgkgX z!J8h}jH}-@evkL#)hk~+8LMtgoED7T>P;PQn6H}&JX@Rn)wk0rhS2@`+y(E$`NzEo zqs1~{%fS1lyyY*j3Fv&ui;kSa;U!*j1j_mH9$Df{sbSDHL1SvxpSSdS7bzqAjUF7? zPWEKU;Tn1K$j$oJ`i4+_>ju-!VIy+g91@3^$1T0dG&JEWcaGvkg5+*-BgdqQe?N-8 zm7%;l8`$LB%3w!TyGC8E>2&q-@BSsT?!MJNQUJ?8u_^b{?tb%yIK>fZj83g@@Em~@ zDNO`#;Al~6ZNI838FxqGdeiX-{&4tmOVecCR3CC3+|{A_mfKg>qTh-6ykYX^`|}r$ zeXbUo%rilrSH+K;3RA=?^UaYvF5^>EDjYtJO#80haG>iV>-ik*PNWAccev<~ukiGef7J7m zTfxG#D4{dSk3%15OqzAL9a_EBgEcY5LwY>+LHNweF+Jxp4>9oPGK2IT5sTS)edvkA z$=#Us6+ys9L+BXdq4eG>XN(qc!miPFO6@t@yC2&Dg(-=B&1%|ht+!s&tM&Jtdte73 zTfhF|@Wz?fFk1;7>V7Bakea<3>^nD?TWL%eCy-x&4zrp)O=jx_inKb@NAJD+832p0 z%;jK`t8E~r=ZrIS()}=zPmxyH!ZFs>*7Xh$)$?kXchc6V`%1KL!H*LaoQ1rLu+Md z-PQ_6IMv16*3gBwwjM5QPk(F=zw0t>6fag9cU8fGvn+SF_ZMyH@j1^TVde=7Zp5MU zwhTK6lmwPM5V!KVSCYKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z00039Nklb-gaQaX#Yek$1S&nNXKn65!x^hb zEl$OJA2MULr4ok9QtfjFY+V?8K4rO7fb#;9Jnp#U2bup)1QSd!!2}abFu?>9OfbO& f6HM?wfL{Xu$|{)z-1!v{00000NkvXXu0mjf8RVH& literal 0 HcmV?d00001 From dd31e75b56bf0ac739cd9eb978ef41e700f09945 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 25 May 2012 14:47:33 +0200 Subject: [PATCH 05/32] fixing bugs 675 and 469; leaderboard sorting is done in the backend; makes non-participant race column contents empty --- .../impl/AbstractLeaderboardImpl.java | 3 +- .../domain/tracking/impl/TrackedLegImpl.java | 1 + .../domain/tracking/impl/TrackedRaceImpl.java | 8 ++- .../gwt/ui/leaderboard/LeaderboardPanel.java | 26 +++++----- .../sailing/gwt/ui/leaderboard/LegColumn.java | 2 +- .../ui/leaderboard/NetPointsComparator.java | 35 ------------- .../gwt/ui/server/SailingServiceImpl.java | 50 +++++++++++++------ .../gwt/ui/shared/AbstractLeaderboardDTO.java | 49 +++--------------- .../sailing/gwt/ui/shared/LeaderboardDTO.java | 16 +++++- 9 files changed, 79 insertions(+), 111 deletions(-) delete mode 100755 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/NetPointsComparator.java diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java index cb6856f2d62..34b15815591 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java @@ -233,7 +233,8 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard { boolean discarded = isDiscarded(competitor, race, timePoint); return new EntryImpl(trackedPoints, correctedResults.getCorrectedScore(), correctedResults.isCorrected(), discarded ? 0 - : correctedResults.getCorrectedScore() * (race.isMedalRace() ? 2 : 1), correctedResults.getMaxPointsReason(), discarded); + : correctedResults.getCorrectedScore() * (race.isMedalRace() ? MEDAL_RACE_FACTOR : 1), + correctedResults.getMaxPointsReason(), discarded); } @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java index 0935ca786c5..807c0e16c7a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java @@ -104,6 +104,7 @@ public class TrackedLegImpl implements TrackedLeg, RaceChangeListener { } // ensure that race isn't updated by events as we're tying to sort the competitors synchronized (getTrackedRace()) { + // TODO See bug 469; competitors already disqualified may need to be ranked worst Collections.sort(rankedCompetitorList, new WindwardToGoComparator(this, timePoint)); rankedCompetitorList = Collections.unmodifiableList(rankedCompetitorList); synchronized (competitorTracksOrderedByRank) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java index 72ee763abd4..e0b74088f6d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -623,7 +623,13 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { @Override public synchronized int getRank(Competitor competitor, TimePoint timePoint) throws NoWindException { try { - return getRanks(timePoint).indexOf(competitor) + 1; + int result; + if (getMarkPassings(competitor).isEmpty()) { + result = 0; + } else { + result = getRanks(timePoint).indexOf(competitor) + 1; + } + return result; } catch (NoWindError e) { throw e.getCause(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java index 893cf08e8b3..91abf9b3b57 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java @@ -45,9 +45,9 @@ import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SelectionChangeEvent.Handler; import com.google.gwt.view.client.SelectionModel; import com.sap.sailing.domain.common.DetailType; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.gwt.ui.actions.AsyncActionsExecutor; import com.sap.sailing.gwt.ui.actions.GetLeaderboardByNameAction; import com.sap.sailing.gwt.ui.client.Collator; @@ -63,7 +63,6 @@ import com.sap.sailing.gwt.ui.client.Timer.PlayModes; import com.sap.sailing.gwt.ui.client.Timer.PlayStates; import com.sap.sailing.gwt.ui.client.UserAgentChecker.UserAgentTypes; import com.sap.sailing.gwt.ui.leaderboard.LegDetailColumn.LegDetailField; -import com.sap.sailing.gwt.ui.leaderboard.NetPointsComparator.SortOrderCalculator; import com.sap.sailing.gwt.ui.shared.CompetitorDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardEntryDTO; @@ -478,17 +477,18 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta @Override public Comparator getComparator() { - if (race.isMedalRace()) { - return getLeaderboard().getMedalRaceComparator(race.getRaceColumnName()); - } else { - SortOrderCalculator sortOrderCalculator = new SortOrderCalculator() { - @Override - public boolean isAscending() { - return isSortedAscendingForThisColumn(getLeaderboardPanel().getLeaderboardTable()); - } - }; - return new NetPointsComparator(sortOrderCalculator, race.getRaceColumnName()); - } + return new Comparator() { + @Override + public int compare(LeaderboardRowDTO o1, LeaderboardRowDTO o2) { + List competitorsFromBestToWorst = getLeaderboard().getCompetitorsFromBestToWorst(race); + boolean ascending = isSortedAscendingForThisColumn(getLeaderboardPanel().getLeaderboardTable()); + int o1Rank = competitorsFromBestToWorst.indexOf(o1.competitor) + 1; + int o2Rank = competitorsFromBestToWorst.indexOf(o2.competitor) + 1; + return o1Rank == 0 ? o2Rank == 0 ? 0 + : ascending ? 1 : -1 : o2Rank == 0 ? ascending ? -1 : 1 + : o1Rank - o2Rank; + } + }; } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LegColumn.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LegColumn.java index d851e07deb3..1a044829729 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LegColumn.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LegColumn.java @@ -326,7 +326,7 @@ public class LegColumn extends ExpandableSortableColumn { @Override public String getValue(LeaderboardRowDTO row) { LegEntryDTO legEntry = getLegEntry(row); - if (legEntry != null) { + if (legEntry != null && legEntry.rank != null) { return ""+legEntry.rank; } else { return ""; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/NetPointsComparator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/NetPointsComparator.java deleted file mode 100755 index 9935ba572b3..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/NetPointsComparator.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.sap.sailing.gwt.ui.leaderboard; - -import java.util.Comparator; - -import com.sap.sailing.gwt.ui.shared.LeaderboardEntryDTO; -import com.sap.sailing.gwt.ui.shared.LeaderboardRowDTO; - -public class NetPointsComparator implements Comparator { - private final SortOrderCalculator sortOrderCalculator; - private final String raceName; - - public interface SortOrderCalculator { - boolean isAscending(); - } - - public NetPointsComparator(SortOrderCalculator sortOrderCalculator, String raceName) { - super(); - this.sortOrderCalculator = sortOrderCalculator; - this.raceName = raceName; - } - - /** - * sorts a meaningless 0 value to the bottom always, regardless whether ascending/descending sorting is - * requested - */ - @Override - public int compare(LeaderboardRowDTO o1, LeaderboardRowDTO o2) { - boolean ascending = sortOrderCalculator.isAscending(); - LeaderboardEntryDTO o1Entry = o1.fieldsByRaceName.get(raceName); - LeaderboardEntryDTO o2Entry = o2.fieldsByRaceName.get(raceName); - return (o1Entry == null || o1Entry.netPoints == 0) ? (o2Entry == null || o2Entry.netPoints == 0) ? 0 - : ascending ? 1 : -1 : (o2Entry == null || o2Entry.netPoints == 0) ? ascending ? -1 : 1 - : o1Entry.netPoints - o2Entry.netPoints; - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 6417a74b14b..c1231aea193 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -19,6 +19,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.WeakHashMap; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; @@ -214,8 +215,11 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS private final Executor executor; + private final WeakHashMap weakCompetitorDTOCache; + public SailingServiceImpl() { BundleContext context = Activator.getDefault(); + weakCompetitorDTOCache = new WeakHashMap(); racingEventServiceTracker = createAndOpenRacingEventServiceTracker(context); replicationServiceTracker = createAndOpenReplicationServiceTracker(context); mongoObjectFactory = MongoFactory.INSTANCE.getDefaultMongoObjectFactory(); @@ -258,7 +262,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS result.name = leaderboard.getName(); result.competitorDisplayNames = new HashMap(); for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { - result.createEmptyRaceColumn(raceColumn.getName(), raceColumn.isMedalRace()); + RaceColumnDTO raceColumnDTO = result.createEmptyRaceColumn(raceColumn.getName(), raceColumn.isMedalRace()); for (Fleet fleet : raceColumn.getFleets()) { RegattaAndRaceIdentifier raceIdentifier = null; TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); @@ -269,6 +273,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS result.addRace(raceColumn.getName(), fleet.getName(), raceColumn.isMedalRace(), raceIdentifier, /* StrippedRaceDTO */ null); } + result.setCompetitorsFromBestToWorst(raceColumnDTO, getCompetitorDTOList(leaderboard.getCompetitorsFromBestToWorst(raceColumn, timePoint))); } result.rows = new HashMap(); result.hasCarriedPoints = leaderboard.hasCarriedPoints(); @@ -285,15 +290,15 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS final Entry entry = leaderboard.getEntry(competitor, raceColumn, timePoint); RunnableFuture future = new FutureTask(new Callable() { @Override - public LeaderboardEntryDTO call() { - try { - return getLeaderboardEntryDTO(entry, raceColumn.getTrackedRace(competitor), competitor, timePoint, - namesOfRaceColumnsForWhichToLoadLegDetails != null - && namesOfRaceColumnsForWhichToLoadLegDetails.contains(raceColumn.getName())); - } catch (NoWindException e) { - throw new NoWindError(e); - } - } + public LeaderboardEntryDTO call() { + try { + return getLeaderboardEntryDTO(entry, raceColumn.getTrackedRace(competitor), competitor, timePoint, + namesOfRaceColumnsForWhichToLoadLegDetails != null + && namesOfRaceColumnsForWhichToLoadLegDetails.contains(raceColumn.getName())); + } catch (NoWindException e) { + throw new NoWindError(e); + } + } }); executor.execute(future); futuresForColumnName.put(raceColumn.getName(), future); @@ -319,6 +324,14 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS return result; } + private List getCompetitorDTOList(List competitorsFromBestToWorst) { + List result = new ArrayList(); + for (Competitor competitor : competitorsFromBestToWorst) { + result.add(getCompetitorDTO(competitor)); + } + return result; + } + @Override public void stressTestLeaderboardByName(String leaderboardName, int times) throws Exception { Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); @@ -474,12 +487,17 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS } private CompetitorDTO getCompetitorDTO(Competitor c) { - CountryCode countryCode = c.getTeam().getNationality().getCountryCode(); - CompetitorDTO competitorDTO = new CompetitorDTO(c.getName(), countryCode == null ? "" - : countryCode.getTwoLetterISOCode(), countryCode == null ? "" : countryCode.getThreeLetterIOCCode(), - countryCode == null ? "" : countryCode.getName(), c.getBoat().getSailID(), c.getId().toString(), - new BoatClassDTO(c.getBoat().getBoatClass().getName(), c.getBoat().getBoatClass().getHullLength() - .getMeters())); + CompetitorDTO competitorDTO = weakCompetitorDTOCache.get(c); + if (competitorDTO == null) { + CountryCode countryCode = c.getTeam().getNationality().getCountryCode(); + competitorDTO = new CompetitorDTO(c.getName(), countryCode == null ? "" + : countryCode.getTwoLetterISOCode(), + countryCode == null ? "" : countryCode.getThreeLetterIOCCode(), countryCode == null ? "" + : countryCode.getName(), c.getBoat().getSailID(), c.getId().toString(), + new BoatClassDTO(c.getBoat().getBoatClass().getName(), c.getBoat().getBoatClass().getHullLength() + .getMeters())); + weakCompetitorDTOCache.put(c, competitorDTO); + } return competitorDTO; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/AbstractLeaderboardDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/AbstractLeaderboardDTO.java index 5c400e5be3c..7cbb5a1e0f3 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/AbstractLeaderboardDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/AbstractLeaderboardDTO.java @@ -2,7 +2,6 @@ package com.sap.sailing.gwt.ui.shared; import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Map; @@ -32,10 +31,6 @@ public abstract class AbstractLeaderboardDTO implements IsSerializable { } } - public Comparator getMedalRaceComparator(String medalRaceName) { - return new MedalRaceComparator(medalRaceName); - } - /** * If the race whose name is specified in raceName has any competitor who has valid * {@link LeaderboardEntryDTO#legDetails} for that race, the number of entries in the leg details is returned, @@ -72,39 +67,6 @@ public abstract class AbstractLeaderboardDTO implements IsSerializable { return totalPoints; } - private class MedalRaceComparator implements Comparator { - private final String medalRaceName; - - public MedalRaceComparator(String medalRaceName) { - this.medalRaceName = medalRaceName; - } - - @Override - public int compare(LeaderboardRowDTO o1, LeaderboardRowDTO o2) { - int result; - if (scoredInMedalRace(o1.competitor)) { - if (scoredInMedalRace(o2.competitor)) { - // both scored in medal race - result = o1.fieldsByRaceName.get(medalRaceName).netPoints - - o2.fieldsByRaceName.get(medalRaceName).netPoints; - } else { - // only o1 scored in medal race, so o1 scores better = "less" - result = -1; - } - } else { - if (scoredInMedalRace(o2.competitor)) { - // only o2 scored in medal race, so o2 scores better, o1 scores worse = "greater" - result = 1; - } else { - // neither one scored in any medal race; to be considered equal for medal race comparison - result = 0; - } - - } - return result; - } - } - public int getNetPoints(CompetitorDTO competitor, String nameOfLastRaceSoFar) { int result = 0; LeaderboardRowDTO row = rows.get(competitor); @@ -186,11 +148,12 @@ public abstract class AbstractLeaderboardDTO implements IsSerializable { races.add(index, raceInLeaderboardDTO); } - public void createEmptyRaceColumn(String raceColumnName, boolean medalRace) { - RaceColumnDTO raceInLeaderboardDTO = new RaceColumnDTO(); - raceInLeaderboardDTO.setRaceColumnName(raceColumnName); - raceInLeaderboardDTO.setMedalRace(medalRace); - races.add(raceInLeaderboardDTO); + public RaceColumnDTO createEmptyRaceColumn(String raceColumnName, boolean medalRace) { + RaceColumnDTO raceColumn = new RaceColumnDTO(); + raceColumn.setRaceColumnName(raceColumnName); + raceColumn.setMedalRace(medalRace); + races.add(raceColumn); + return raceColumn; } protected RaceColumnDTO getRaceInLeaderboardByName(String raceColumnName) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardDTO.java index 1c83bdd6c7b..7a45bcf2224 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardDTO.java @@ -1,6 +1,8 @@ package com.sap.sailing.gwt.ui.shared; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.google.gwt.user.client.rpc.IsSerializable; @@ -17,8 +19,20 @@ public class LeaderboardDTO extends AbstractLeaderboardDTO implements IsSerializ * The competitor list, ordered ascending by total rank */ public List competitors; + + private Map> competitorOrderingPerRace; - public LeaderboardDTO() {} + public LeaderboardDTO() { + competitorOrderingPerRace = new HashMap>(); + } + + public void setCompetitorsFromBestToWorst(RaceColumnDTO raceColumn, List orderedCompetitors) { + competitorOrderingPerRace.put(raceColumn, orderedCompetitors); + } + + public List getCompetitorsFromBestToWorst(RaceColumnDTO raceColumn) { + return competitorOrderingPerRace.get(raceColumn); + } public int getRank(CompetitorDTO competitor) { return competitors.indexOf(competitor) + 1; From 4c4cea5e998bd9858f15780336dbf0e833bde97e Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 25 May 2012 15:33:36 +0200 Subject: [PATCH 06/32] pass score comparator into leaderboard --- .../impl/DomainObjectFactoryImpl.java | 3 +- ...aderboardImplWithDelayedCarriedPoints.java | 5 +-- .../test/LeaderboardForKielWeekTest.java | 4 ++- .../domain/test/LeaderboardOfflineTest.java | 9 +++--- .../LeaderboardScoringAndRankingTest.java | 3 +- .../impl/AbstractLeaderboardImpl.java | 32 +++++++++++++++++-- .../impl/FlexibleLeaderboardImpl.java | 5 +-- .../impl/LeaderboardTotalRankComparator.java | 11 +++---- .../leaderboard/impl/LowerScoreIsBetter.java | 17 ++++++++++ .../impl/RegattaLeaderboardImpl.java | 6 ++-- .../sailing/gwt/ui/leaderboard/LegColumn.java | 2 +- .../sailing/gwt/ui/shared/LegEntryDTO.java | 9 ++---- ...StoringAndRetrievingLeaderboardGroups.java | 21 ++++++------ .../TestStoringAndRetrievingLeaderboards.java | 11 ++++--- .../server/impl/RacingEventServiceImpl.java | 3 +- 15 files changed, 95 insertions(+), 46 deletions(-) create mode 100755 java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index 26015070d85..a441924f954 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -51,6 +51,7 @@ import com.sap.sailing.domain.leaderboard.LeaderboardGroup; import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; +import com.sap.sailing.domain.leaderboard.impl.LowerScoreIsBetter; import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.persistence.DomainObjectFactory; @@ -170,7 +171,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } ThresholdBasedResultDiscardingRule resultDiscardingRule = new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces); FlexibleLeaderboardImplWithDelayedCarriedPoints result = new FlexibleLeaderboardImplWithDelayedCarriedPoints( - (String) o.get(FieldNames.LEADERBOARD_NAME.name()), scoreCorrection, resultDiscardingRule); + (String) o.get(FieldNames.LEADERBOARD_NAME.name()), scoreCorrection, resultDiscardingRule, new LowerScoreIsBetter()); BasicDBList dbRaceColumns = (BasicDBList) o.get(FieldNames.LEADERBOARD_COLUMNS.name()); // For a FlexibleLeaderboard, fleets are owned by the leaderboard's RaceColumn objects. We need to manage them here: Map fleetsByName = new HashMap(); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FlexibleLeaderboardImplWithDelayedCarriedPoints.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FlexibleLeaderboardImplWithDelayedCarriedPoints.java index 66305f59168..6c44451f865 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FlexibleLeaderboardImplWithDelayedCarriedPoints.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FlexibleLeaderboardImplWithDelayedCarriedPoints.java @@ -1,5 +1,6 @@ package com.sap.sailing.domain.persistence.impl; +import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -60,8 +61,8 @@ public class FlexibleLeaderboardImplWithDelayedCarriedPoints extends FlexibleLea } public FlexibleLeaderboardImplWithDelayedCarriedPoints(String name, SettableScoreCorrection scoreCorrection, - ThresholdBasedResultDiscardingRule resultDiscardingRule) { - super(name, scoreCorrection, resultDiscardingRule); + ThresholdBasedResultDiscardingRule resultDiscardingRule, Comparator scoreComparator) { + super(name, scoreCorrection, resultDiscardingRule, scoreComparator); carriedPointsByCompetitorName = new HashMap(); maxPointsReasonsByCompetitorName = new HashMap>(); correctedScoresByCompetitorName = new HashMap>(); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java index b14faa6a43f..bb5a2211a1d 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java @@ -20,6 +20,7 @@ import com.sap.sailing.domain.common.impl.DegreeBearingImpl; import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.common.impl.WindSourceImpl; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; +import com.sap.sailing.domain.leaderboard.impl.LowerScoreIsBetter; import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.tracking.impl.WindImpl; @@ -35,7 +36,8 @@ public class LeaderboardForKielWeekTest extends OnlineTracTracBasedTest { @Test public void leaderboardWithOneRaceTest() throws URISyntaxException, NoWindException, IOException, InterruptedException { - leaderboard = new FlexibleLeaderboardImpl("Kiel Week 2011 505s", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(new int[] { 3, 6 })); + leaderboard = new FlexibleLeaderboardImpl("Kiel Week 2011 505s", new ScoreCorrectionImpl(), + new ResultDiscardingRuleImpl(new int[] { 3, 6 }), new LowerScoreIsBetter()); Fleet defaultFleet = leaderboard.getFleet(null); MillisecondsTimePoint now = MillisecondsTimePoint.now(); loadRace("357c700a-9d9a-11e0-85be-406186cbf87c"); // 505 Race 2 diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java index 45cc683e36d..62638d0fc45 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java @@ -25,6 +25,7 @@ import com.sap.sailing.domain.common.impl.Util; import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; +import com.sap.sailing.domain.leaderboard.impl.LowerScoreIsBetter; import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.tracking.TrackedRace; @@ -85,7 +86,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { @Test public void ensureMedalRaceParamIsIgnoredIfRaceColumnAlreadyExists() { FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl( - new int[] { 5, 8 })); + new int[] { 5, 8 }), new LowerScoreIsBetter()); Fleet defaultFleet = leaderboard.getFleet(null); final String columnName = "abc"; setupRaces(1, 0); @@ -108,7 +109,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { } ScoreCorrectionImpl scoreCorrection = new ScoreCorrectionImpl(); FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ResultDiscardingRuleImpl( - new int[] { 1 })); + new int[] { 1 }), new LowerScoreIsBetter()); Fleet defaultFleet = leaderboard.getFleet(null); int i=0; int bestScore = Integer.MAX_VALUE; @@ -144,7 +145,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { } ScoreCorrectionImpl scoreCorrection = new ScoreCorrectionImpl(); FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ResultDiscardingRuleImpl( - new int[] { 1 })); + new int[] { 1 }), new LowerScoreIsBetter()); Fleet defaultFleet = leaderboard.getFleet(null); int i=0; int bestScore = Integer.MAX_VALUE; @@ -171,7 +172,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { int secondDiscardingThreshold, Integer carry, boolean addOneMedalRace, int numberOfUntrackedRaces) throws NoWindException { setupRaces(numberOfStartedRaces, numberOfNotStartedRaces); FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl( - new int[] { firstDiscardingThreshold, secondDiscardingThreshold })); + new int[] { firstDiscardingThreshold, secondDiscardingThreshold }), new LowerScoreIsBetter()); Fleet defaultFleet = leaderboard.getFleet(null); int i=0; for (TrackedRace race : testRaces) { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java index bc7fcd4a150..f1fe6920cd2 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java @@ -25,6 +25,7 @@ import com.sap.sailing.domain.base.impl.SeriesImpl; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.impl.LowerScoreIsBetter; import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; @@ -36,7 +37,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { private Leaderboard createLeaderboard(Regatta regatta, int[] discardingThresholds) { ScoreCorrectionImpl scoreCorrections = new ScoreCorrectionImpl(); ResultDiscardingRuleImpl discardingRules = new ResultDiscardingRuleImpl(discardingThresholds); - return new RegattaLeaderboardImpl(regatta, scoreCorrections, discardingRules); + return new RegattaLeaderboardImpl(regatta, scoreCorrections, discardingRules, new LowerScoreIsBetter()); } @Test diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java index 34b15815591..70794722b31 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java @@ -18,6 +18,7 @@ import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.impl.Util; import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.ScoreCorrection; import com.sap.sailing.domain.leaderboard.ScoreCorrection.Result; import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; @@ -46,6 +47,8 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard { * provided by this map are considered by {@link #getTotalPoints(Competitor, TimePoint)}. */ private final Map carriedPoints; + + private final Comparator scoreComparator; /** * A leaderboard entry representing a snapshot of a cell at a given time point for a single race/competitor. @@ -96,13 +99,16 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard { } /** + * @param scoreComparator TODO * @param name must not be null */ - public AbstractLeaderboardImpl(SettableScoreCorrection scoreCorrection, ThresholdBasedResultDiscardingRule resultDiscardingRule) { + public AbstractLeaderboardImpl(SettableScoreCorrection scoreCorrection, + ThresholdBasedResultDiscardingRule resultDiscardingRule, Comparator scoreComparator) { this.carriedPoints = new HashMap(); this.scoreCorrection = scoreCorrection; this.displayNames = new HashMap(); this.resultDiscardingRule = resultDiscardingRule; + this.scoreComparator = scoreComparator; } @Override @@ -186,7 +192,27 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard { @Override public int getTrackedRank(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException { final TrackedRace trackedRace = race.getTrackedRace(competitor); - return trackedRace == null ? 0 : trackedRace.hasStarted(timePoint) ? trackedRace.getRank(competitor, timePoint) : 0; + return trackedRace == null ? 0 + : trackedRace.hasStarted(timePoint) ? improveByDisqualificationsOfBetterRankedCompetitors(race, timePoint, trackedRace + .getRank(competitor, timePoint)) : 0; + } + + /** + * Per competitor disqualified ({@link ScoreCorrection} has a {@link MaxPointsReason} for the competitor), all + * competitors ranked worse by the tracking system need to have their rank corrected by one. + * + * @param timePoint + * time point at which to consider disqualifications (not used yet because currently we don't remember + * when a competitor was disqualified) + * @param race the race column to which the rank refers; look for disqualifications / max points reasons in this column + * @param rank a competitors rank according to the tracking system + * @return the unmodified rank if no disqualifications for better-ranked competitors exist for race, + * or otherwise a rank improved (lowered) by the number of disqualifications of competitors whose tracked rank is better (lower) + * than rank. + */ + private int improveByDisqualificationsOfBetterRankedCompetitors(RaceColumn race, TimePoint timePoint, int rank) { + // TODO Auto-generated method stub + return 0; } @Override @@ -366,6 +392,6 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard { } protected Comparator getTotalRankComparator(TimePoint timePoint) { - return new LeaderboardTotalRankComparator(this, timePoint); + return new LeaderboardTotalRankComparator(this, timePoint, scoreComparator); } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java index 338e7a7a643..a8a990aae49 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java @@ -3,6 +3,7 @@ package com.sap.sailing.domain.leaderboard.impl; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.logging.Logger; @@ -31,8 +32,8 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements private String name; public FlexibleLeaderboardImpl(String name, SettableScoreCorrection scoreCorrection, - ThresholdBasedResultDiscardingRule resultDiscardingRule) { - super(scoreCorrection, resultDiscardingRule); + ThresholdBasedResultDiscardingRule resultDiscardingRule, Comparator scoreComparator) { + super(scoreCorrection, resultDiscardingRule, scoreComparator); if (name == null) { throw new IllegalArgumentException("A leaderboard's name must not be null"); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java index 8e250308c5a..a6c7fff6c2f 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java @@ -46,11 +46,13 @@ import com.sap.sailing.domain.leaderboard.Leaderboard; public class LeaderboardTotalRankComparator implements Comparator { private final Leaderboard leaderboard; private final TimePoint timePoint; + private final Comparator scoreComparator; - public LeaderboardTotalRankComparator(Leaderboard leaderboard, TimePoint timePoint) { + public LeaderboardTotalRankComparator(Leaderboard leaderboard, TimePoint timePoint, Comparator scoreComparator) { super(); this.leaderboard = leaderboard; this.timePoint = timePoint; + this.scoreComparator = scoreComparator; } protected Leaderboard getLeaderboard() { @@ -202,12 +204,7 @@ public class LeaderboardTotalRankComparator implements Comparator { * the integer numbers by their natural ordering. */ protected Comparator getScoreComparator() { - return new Comparator() { - @Override - public int compare(Integer o1, Integer o2) { - return o1-o2; - } - }; + return scoreComparator; } /** diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java new file mode 100755 index 00000000000..20298e59423 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java @@ -0,0 +1,17 @@ +package com.sap.sailing.domain.leaderboard.impl; + +import java.util.Comparator; + +/** + * The score comparator as used by the ISAF standard scoring scheme. Lower scores are better. + * + * @author Axel Uhl (D043530) + * + */ +public class LowerScoreIsBetter implements Comparator { + @Override + public int compare(Integer o1, Integer o2) { + return o1-o2; + } + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java index f5d90cdbd10..912d26fce6f 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.leaderboard.impl; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import com.sap.sailing.domain.base.Fleet; @@ -22,8 +23,9 @@ public class RegattaLeaderboardImpl extends AbstractLeaderboardImpl { private static final long serialVersionUID = 2370461218294770084L; private final Regatta regatta; - public RegattaLeaderboardImpl(Regatta regatta, SettableScoreCorrection scoreCorrection, ThresholdBasedResultDiscardingRule resultDiscardingRule) { - super(scoreCorrection, resultDiscardingRule); + public RegattaLeaderboardImpl(Regatta regatta, SettableScoreCorrection scoreCorrection, + ThresholdBasedResultDiscardingRule resultDiscardingRule, Comparator scoreComparator) { + super(scoreCorrection, resultDiscardingRule, scoreComparator); this.regatta = regatta; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LegColumn.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LegColumn.java index 1a044829729..49980317811 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LegColumn.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LegColumn.java @@ -326,7 +326,7 @@ public class LegColumn extends ExpandableSortableColumn { @Override public String getValue(LeaderboardRowDTO row) { LegEntryDTO legEntry = getLegEntry(row); - if (legEntry != null && legEntry.rank != null) { + if (legEntry != null && legEntry.rank != 0) { return ""+legEntry.rank; } else { return ""; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LegEntryDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LegEntryDTO.java index f657164a402..0a18f9310b0 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LegEntryDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LegEntryDTO.java @@ -13,7 +13,7 @@ import com.google.gwt.user.client.rpc.IsSerializable; public class LegEntryDTO implements IsSerializable { public Double distanceTraveledInMeters; public Double averageSpeedOverGroundInKnots; - public Integer rank; + public int rank; public Double gapToLeaderInSeconds; public Double estimatedTimeToNextWaypointInSeconds; @@ -57,7 +57,7 @@ public class LegEntryDTO implements IsSerializable { result = prime * result + ((numberOfJibes == null) ? 0 : numberOfJibes.hashCode()); result = prime * result + ((numberOfPenaltyCircles == null) ? 0 : numberOfPenaltyCircles.hashCode()); result = prime * result + ((numberOfTacks == null) ? 0 : numberOfTacks.hashCode()); - result = prime * result + ((rank == null) ? 0 : rank.hashCode()); + result = prime * result + rank; result = prime * result + (started ? 1231 : 1237); result = prime * result + (int) (timeInMilliseconds ^ (timeInMilliseconds >>> 32)); result = prime * result + ((velocityMadeGoodInKnots == null) ? 0 : velocityMadeGoodInKnots.hashCode()); @@ -116,10 +116,7 @@ public class LegEntryDTO implements IsSerializable { return false; } else if (!numberOfTacks.equals(other.numberOfTacks)) return false; - if (rank == null) { - if (other.rank != null) - return false; - } else if (!rank.equals(other.rank)) + if (rank != other.rank) return false; if (started != other.started) return false; diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java index 703adcbfd6a..6feb1fa0bad 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java @@ -15,6 +15,7 @@ import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.LeaderboardGroup; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; +import com.sap.sailing.domain.leaderboard.impl.LowerScoreIsBetter; import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.persistence.DomainObjectFactory; @@ -43,16 +44,16 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final ArrayList leaderboards = new ArrayList<>(); Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)); + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()); leaderboards.add(leaderboard); leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)); + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()); leaderboards.add(leaderboard); leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)); + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()); leaderboards.add(leaderboard); leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)); + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()); leaderboards.add(leaderboard); final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, leaderboards); @@ -80,10 +81,10 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final ArrayList leaderboards = new ArrayList<>(); Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)); + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()); leaderboards.add(leaderboard); leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)); + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()); leaderboards.add(leaderboard); final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, leaderboards); @@ -93,11 +94,11 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final Leaderboard[] ungroupedLeaderboards = { new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[0], new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)), + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()), new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[1], new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)), + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()), new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[2], new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)) }; + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()) }; mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[0]); mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[1]); mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[2]); @@ -133,7 +134,7 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe final String groupDescription = "A leaderboard group"; final ArrayList leaderboards = new ArrayList<>(); - final FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)); + final FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()); final Fleet fleet = leaderboard.getFleet(null); final RaceColumn race = leaderboard.addRaceColumn(columnName, false, fleet); leaderboards.add(leaderboard); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java index f9a899ce780..d90a6701062 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboards.java @@ -22,6 +22,7 @@ import com.sap.sailing.domain.common.impl.Util; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; +import com.sap.sailing.domain.leaderboard.impl.LowerScoreIsBetter; import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl; @@ -35,7 +36,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final String leaderboardName = "TestLeaderboard"; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)); + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()); new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard); Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName); assertEquals(leaderboardName, loadedLeaderboard.getName()); @@ -50,7 +51,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int carriedPointsForWolfgangHunger = 3; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)); + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()); Competitor competitor = createCompetitor(); TrackedRace raceWithOneCompetitor = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); leaderboard.addRace(raceWithOneCompetitor, raceColumnName, /* medalRace */ false, leaderboard.getFleet(null)); @@ -75,7 +76,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final int correctedPoints = 2; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)); + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()); Competitor competitor = createCompetitor(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); @@ -101,7 +102,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final MaxPointsReason maxPointsReason = MaxPointsReason.DNF; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)); + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()); Competitor competitor = createCompetitor(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); @@ -128,7 +129,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest { final MaxPointsReason maxPointsReason = MaxPointsReason.DNF; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)); + new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowerScoreIsBetter()); Competitor competitor = createCompetitor(); TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true); TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index adbd443653f..66609932de2 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -51,6 +51,7 @@ import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.LeaderboardGroup; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; +import com.sap.sailing.domain.leaderboard.impl.LowerScoreIsBetter; import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.persistence.DomainObjectFactory; @@ -207,7 +208,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen @Override public Leaderboard addFlexibleLeaderboard(String name, int[] discardThresholds) { Leaderboard result = new FlexibleLeaderboardImpl(name, new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl( - discardThresholds)); + discardThresholds), new LowerScoreIsBetter()); synchronized (leaderboardsByName) { if (leaderboardsByName.containsKey(name)) { throw new IllegalArgumentException("Leaderboard with name "+name+" already exists"); From 76b40b304d581301e92fd0d9bec7d1eebfb543c4 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 25 May 2012 16:01:32 +0200 Subject: [PATCH 07/32] fixed TrackedRace mock implementations regarding getCompetitorsFromBestToWorst --- .../LeaderboardScoringAndRankingTest.java | 28 +++++++++++++++++++ .../test/MockedTrackedRaceWithFixedRank.java | 6 ++++ ...ockedTrackedRaceWithStartTimeAndRanks.java | 5 ++++ .../domain/test/mock/MockedTrackedRace.java | 6 ++++ .../impl/AbstractLeaderboardImpl.java | 28 +++++++++++++------ .../impl/LeaderboardTotalRankComparator.java | 2 +- .../sailing/domain/tracking/TrackedRace.java | 6 ++++ .../domain/tracking/impl/TrackedRaceImpl.java | 7 +++-- 8 files changed, 76 insertions(+), 12 deletions(-) diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java index f1fe6920cd2..9473a6b4b9f 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java @@ -22,6 +22,7 @@ import com.sap.sailing.domain.base.impl.FleetImpl; import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; import com.sap.sailing.domain.base.impl.RegattaImpl; import com.sap.sailing.domain.base.impl.SeriesImpl; +import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.leaderboard.Leaderboard; @@ -57,6 +58,33 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { assertEquals(competitors, rankedCompetitors); } + /** + * Asserts that the competitors ranking worse than the disqualified competitor advance by one + */ + @Test + public void testOneStartedRaceWithDifferentScoresAndDisqualification() { + List competitors = createCompetitors(10); + Regatta regatta = createRegatta(/* qualifying */0, new String[] { "Default" }, /* final */1, + new String[] { "Default" }, + /* medal */false, "testOneStartedRaceWithDifferentScores", + DomainFactory.INSTANCE.getOrCreateBoatClass("49er", /* typicallyStartsUpwind */true)); + Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]); + Series finalSeries; + Iterator seriesIter = regatta.getSeries().iterator(); + seriesIter.next(); + finalSeries = seriesIter.next(); + leaderboard.getScoreCorrection().setMaxPointsReason(competitors.get(5), finalSeries.getRaceColumnByName("F1"), MaxPointsReason.DSQ); + TimePoint now = MillisecondsTimePoint.now(); + TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000); + TrackedRace f1 = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors); + RaceColumn f1Column = series.get(1).getRaceColumnByName("F1"); + f1Column.setTrackedRace(f1Column.getFleets().iterator().next(), f1); + List rankedCompetitors = leaderboard.getCompetitorsFromBestToWorst(later); + assertEquals(competitors.subList(0, 5), rankedCompetitors.subList(0, 5)); + assertEquals(competitors.subList(6, 10), rankedCompetitors.subList(5, 9)); + assertEquals(competitors.get(5), rankedCompetitors.get(9)); + } + @Test public void testDistributionAcrossQualifyingFleetsWithDifferentScores() { List competitors = createCompetitors(10); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MockedTrackedRaceWithFixedRank.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MockedTrackedRaceWithFixedRank.java index 631bfdd75ca..0754d2849d7 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MockedTrackedRaceWithFixedRank.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MockedTrackedRaceWithFixedRank.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.test; import java.util.Collections; +import java.util.List; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -43,6 +44,11 @@ public class MockedTrackedRaceWithFixedRank extends MockedTrackedRace { } + @Override + public List getCompetitorsFromBestToWorst(TimePoint timePoint) { + return Collections.singletonList(competitor); + } + @Override public boolean hasStarted(TimePoint at) { return started; diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MockedTrackedRaceWithStartTimeAndRanks.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MockedTrackedRaceWithStartTimeAndRanks.java index 0256502dbe2..38324869486 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MockedTrackedRaceWithStartTimeAndRanks.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MockedTrackedRaceWithStartTimeAndRanks.java @@ -412,4 +412,9 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { return null; } + @Override + public List getCompetitorsFromBestToWorst(TimePoint timePoint) { + return competitorsFromBestToWorst; + } + } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java index f09d95cd292..9021276cf12 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java @@ -620,4 +620,10 @@ public class MockedTrackedRace implements DynamicTrackedRace { // TODO Auto-generated method stub } + + @Override + public List getCompetitorsFromBestToWorst(TimePoint timePoint) { + // TODO Auto-generated method stub + return null; + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java index 70794722b31..f95827ce6a4 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardImpl.java @@ -5,6 +5,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -99,7 +100,7 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard { } /** - * @param scoreComparator TODO + * @param scoreComparator the comparator to use to compare basic scores, such as net points * @param name must not be null */ public AbstractLeaderboardImpl(SettableScoreCorrection scoreCorrection, @@ -193,26 +194,37 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard { public int getTrackedRank(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException { final TrackedRace trackedRace = race.getTrackedRace(competitor); return trackedRace == null ? 0 - : trackedRace.hasStarted(timePoint) ? improveByDisqualificationsOfBetterRankedCompetitors(race, timePoint, trackedRace + : trackedRace.hasStarted(timePoint) ? improveByDisqualificationsOfBetterRankedCompetitors(race, trackedRace, timePoint, trackedRace .getRank(competitor, timePoint)) : 0; } /** * Per competitor disqualified ({@link ScoreCorrection} has a {@link MaxPointsReason} for the competitor), all * competitors ranked worse by the tracking system need to have their rank corrected by one. - * + * @param trackedRace the race to which the rank refers; look for disqualifications / max points reasons in this column * @param timePoint * time point at which to consider disqualifications (not used yet because currently we don't remember * when a competitor was disqualified) - * @param race the race column to which the rank refers; look for disqualifications / max points reasons in this column * @param rank a competitors rank according to the tracking system + * * @return the unmodified rank if no disqualifications for better-ranked competitors exist for race, * or otherwise a rank improved (lowered) by the number of disqualifications of competitors whose tracked rank is better (lower) * than rank. */ - private int improveByDisqualificationsOfBetterRankedCompetitors(RaceColumn race, TimePoint timePoint, int rank) { - // TODO Auto-generated method stub - return 0; + private int improveByDisqualificationsOfBetterRankedCompetitors(RaceColumn raceColumn, TrackedRace trackedRace, TimePoint timePoint, int rank) { + int correctedRank = rank; + List competitorsFromBestToWorst = trackedRace.getCompetitorsFromBestToWorst(timePoint); + int betterCompetitorRank=1; + Iterator ci = competitorsFromBestToWorst.iterator(); + while (betterCompetitorRank < rank && ci.hasNext()) { + Competitor betterTrackedCompetitor = ci.next(); + MaxPointsReason maxPointsReasonForBetterCompetitor = getScoreCorrection().getMaxPointsReason(betterTrackedCompetitor, raceColumn); + if (maxPointsReasonForBetterCompetitor != null && maxPointsReasonForBetterCompetitor != MaxPointsReason.NONE) { + correctedRank--; + } + betterCompetitorRank++; + } + return correctedRank; } @Override @@ -372,7 +384,7 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard { } else { comparisonResult = netPointsAndFleet.get(o1).getB().compareTo(netPointsAndFleet.get(o2).getB()); if (comparisonResult == 0) { - comparisonResult = netPointsAndFleet.get(o1).getA() - netPointsAndFleet.get(o2).getA(); + comparisonResult = scoreComparator.compare(netPointsAndFleet.get(o1).getA(), netPointsAndFleet.get(o2).getA()); } } return comparisonResult; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java index a6c7fff6c2f..f4133e8c6d7 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java @@ -211,7 +211,7 @@ public class LeaderboardTotalRankComparator implements Comparator { * This implementation ranks a competitor better (lesser) if it has the lower score sum */ protected int compareByScoreSum(int o1ScoreSum, int o2ScoreSum) { - return o1ScoreSum - o2ScoreSum; + return getScoreComparator().compare(o1ScoreSum, o2ScoreSum); } /** diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java index 7d73617d284..dc3fc5692d8 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java @@ -391,4 +391,10 @@ public interface TrackedRace extends Serializable { WindStore getWindStore(); Competitor getOverallLeader(TimePoint timePoint) throws NoWindException; + + /** + * Returns the competitors of this tracked race, according to their ranking. Competitors whose {@link #getRank(Competitor)} is 0 will + * be sorted "worst". + */ + List getCompetitorsFromBestToWorst(TimePoint timePoint); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java index e0b74088f6d..d1e31d9b4b7 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -610,7 +610,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { public synchronized Competitor getOverallLeader(TimePoint timePoint) throws NoWindException { try { Competitor result = null; - List ranks = getRanks(timePoint); + List ranks = getCompetitorsFromBestToWorst(timePoint); if (ranks != null && !ranks.isEmpty()) { result = ranks.iterator().next(); } @@ -627,7 +627,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { if (getMarkPassings(competitor).isEmpty()) { result = 0; } else { - result = getRanks(timePoint).indexOf(competitor) + 1; + result = getCompetitorsFromBestToWorst(timePoint).indexOf(competitor) + 1; } return result; } catch (NoWindError e) { @@ -635,7 +635,8 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { } } - private List getRanks(TimePoint timePoint) { + @Override + public List getCompetitorsFromBestToWorst(TimePoint timePoint) { synchronized (competitorRankings) { List rankedCompetitors = competitorRankings.get(timePoint); if (rankedCompetitors == null) { From ecfeb91be79282645b5b6413bbc45f11d74a781d Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 25 May 2012 16:49:47 +0200 Subject: [PATCH 08/32] made LowerScoreIsBetter serializable --- .../sailing/domain/leaderboard/impl/LowerScoreIsBetter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java index 20298e59423..70b8b6b54a2 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java @@ -1,5 +1,6 @@ package com.sap.sailing.domain.leaderboard.impl; +import java.io.Serializable; import java.util.Comparator; /** @@ -8,7 +9,7 @@ import java.util.Comparator; * @author Axel Uhl (D043530) * */ -public class LowerScoreIsBetter implements Comparator { +public class LowerScoreIsBetter implements Comparator, Serializable { @Override public int compare(Integer o1, Integer o2) { return o1-o2; From 861404aadc49fd02f5c40d92ad37f5c8df52a862 Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Fri, 25 May 2012 17:29:21 +0200 Subject: [PATCH 09/32] Set styles to raceBoardNavigation Looks better than the plain variant --- java/com.sap.sailing.gwt.ui/RaceBoard.css | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/RaceBoard.css b/java/com.sap.sailing.gwt.ui/RaceBoard.css index ff15fdeede2..d2e9a700890 100644 --- a/java/com.sap.sailing.gwt.ui/RaceBoard.css +++ b/java/com.sap.sailing.gwt.ui/RaceBoard.css @@ -147,7 +147,7 @@ input.opencoloumn { .raceBoardNavigation { float: left; - margin: 3px;; + margin: 9px 0 0 12px; font-family: 'UbuntuLight', Arial, Verdana, sans-serif; } @@ -196,6 +196,16 @@ input.opencoloumn { .raceBoardNavigation-settingsButtonPanel { float: right; - margin: 3px;; + margin: 9px 12px 0 0; } +.raceBoardNavigation-innerElement { + background: none repeat scroll 0 0 #7C7B7C; + color: #FFFFFF; + margin: 0 10px 0 0; + padding: 2px 9px 2px 3px; + -webkit-border-radius: 3px; +-moz-border-radius: 3px; +border-radius: 3px; +font-family: UbuntuBold,Verdana,Arial,sans-serif; +} \ No newline at end of file From 92131aa0e9a547c53428af59525095b534af4529 Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Fri, 25 May 2012 17:30:26 +0200 Subject: [PATCH 10/32] Set StylesName to checkbox for better CSS styling --- .../java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java index 28b72996238..2d4344ec631 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java @@ -239,6 +239,7 @@ public class RaceBoardPanel extends FormPanel implements RegattaDisplayer, RaceS checkBox.setValue(component.isVisible()); checkBox.setTitle(stringMessages.showHideComponent(component.getLocalizedShortName())); + checkBox.addStyleName("raceBoardNavigation-innerElement"); checkBox.addValueChangeHandler(new ValueChangeHandler() { @Override From 5604b2a9d22594b1fa80f2ddfc62bdd82fbe6806 Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Fri, 25 May 2012 17:35:13 +0200 Subject: [PATCH 11/32] Copy styles form gwt-Button to raceBoardNavigation For better UI integration --- java/com.sap.sailing.gwt.ui/RaceBoard.css | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/RaceBoard.css b/java/com.sap.sailing.gwt.ui/RaceBoard.css index d2e9a700890..42633a0a946 100644 --- a/java/com.sap.sailing.gwt.ui/RaceBoard.css +++ b/java/com.sap.sailing.gwt.ui/RaceBoard.css @@ -147,7 +147,7 @@ input.opencoloumn { .raceBoardNavigation { float: left; - margin: 9px 0 0 12px; + margin: 9px 0 0 7px; font-family: 'UbuntuLight', Arial, Verdana, sans-serif; } @@ -199,13 +199,19 @@ input.opencoloumn { margin: 9px 12px 0 0; } + .raceBoardNavigation-innerElement { - background: none repeat scroll 0 0 #7C7B7C; + background: url("images/btn-cta-orangeleft.png") repeat-x scroll center 0 transparent; + border: medium none; + border-radius: 3px 3px 3px 3px; color: #FFFFFF; - margin: 0 10px 0 0; - padding: 2px 9px 2px 3px; - -webkit-border-radius: 3px; --moz-border-radius: 3px; -border-radius: 3px; -font-family: UbuntuBold,Verdana,Arial,sans-serif; + cursor: pointer; + font-family: UbuntuBold,Verdana,Arial,sans-serif; + font-size: 14px; + margin: 0 0 0 5px; + padding: 2px 7px 2px 3px; +} +.raceBoardNavigation-innerElement:hover { + background: url("images/btn-cta-orangeleft.png") repeat-x scroll center -30px transparent; + cursor: pointer; } \ No newline at end of file From f170c9e85783851febff93589383ebc5006085f9 Mon Sep 17 00:00:00 2001 From: fmittag Date: Fri, 25 May 2012 19:13:51 +0200 Subject: [PATCH 12/32] fixed the checkbox positioning problem in the legend of the charts --- .../gwt/ui/shared/charts/RaceChart.java | 2 +- .../gwt/highcharts/client/BaseChart.java | 25 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/RaceChart.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/RaceChart.java index 9874c48b250..2c547fb58ca 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/RaceChart.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/RaceChart.java @@ -168,7 +168,7 @@ public abstract class RaceChart extends SimplePanel implements RaceTimesInfoProv * visibility state. */ protected void useCheckboxesToShowAndHide(final Chart chart) { - chart.setLegend(new Legend().setEnabled(true).setBorderWidth(0).setSymbolPadding(20)); // make room for checkbox + chart.setLegend(new Legend().setEnabled(true).setBorderWidth(0).setSymbolPadding(25)); // make room for checkbox chart.setSeriesPlotOptions(new SeriesPlotOptions().setSeriesCheckboxClickEventHandler(new SeriesCheckboxClickEventHandler() { @Override public boolean onClick(SeriesCheckboxClickEvent seriesCheckboxClickEvent) { diff --git a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java index 2084705329c..e26b9a34a66 100644 --- a/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java +++ b/java/org.moxieapps.gwt.highcharts/src/org/moxieapps/gwt/highcharts/client/BaseChart.java @@ -1495,7 +1495,6 @@ public abstract class BaseChart extends Widget { // Once we're rendered, we're maintaining the point state in the DOM, so we can dump our internal list to save memory series.clearInternalPointsList(); - nativeAdjustCheckboxPosition(get(series.getId())); } return returnThis(); @@ -1818,6 +1817,7 @@ public abstract class BaseChart extends Widget { public T redraw() { if (isRendered()) { nativeRedraw(chart); + nativeAdjustCheckboxPosition(chart); } return returnThis(); } @@ -1969,7 +1969,6 @@ public abstract class BaseChart extends Widget { for (Series series : seriesList) { series.clearInternalPointsList(); series.setRendered(true); - nativeAdjustCheckboxPosition(get(series.getId())); } } @@ -2489,20 +2488,22 @@ public abstract class BaseChart extends Widget { /** * Fixing a bug currently in the base Highcharts implementation regarding the placement of the checkbox in the legend. - * Requires the symbol padding (see {@link Legend#setSymbolPadding(Number)}) to be set to 20. Invoked - * whenever a series is added / displayed in a rendered chart.

+ * Requires the symbol padding (see {@link Legend#setSymbolPadding(Number)}) to be set to 25. Invoked + * whenever the chart is rendered.

* - * The implementation moves the legend item text 15px to the left, using the space made by setting the symbol - * padding to 20px; the checkbox is moved 18px to the left with the top margin set to 0px. + * The implementation moves the checkbox between the legend symbol and the legend item, using the space made by setting the symbol + * padding to 25px. */ - private static native JavaScriptObject nativeAdjustCheckboxPosition(JavaScriptObject series) /*-{ - if (series.legendItem && series.checkbox) { - series.legendItem.translate(-15, 0); - series.checkbox.style.marginLeft = '-18px' - series.checkbox.style.marginTop = '0px' + private static native JavaScriptObject nativeAdjustCheckboxPosition(JavaScriptObject chart) /*-{ + var series = chart.series; + for(var i= 0; i Date: Fri, 25 May 2012 23:41:12 +0200 Subject: [PATCH 13/32] added serial version UID to LowerScoreIsBetter --- .../sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java index 70b8b6b54a2..a3003932f1d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowerScoreIsBetter.java @@ -10,6 +10,8 @@ import java.util.Comparator; * */ public class LowerScoreIsBetter implements Comparator, Serializable { + private static final long serialVersionUID = -2767385186133743330L; + @Override public int compare(Integer o1, Integer o2) { return o1-o2; From eaa3bb552f6c087f63f9198962745295a56bed87 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 26 May 2012 13:08:35 +0200 Subject: [PATCH 14/32] click now again sets time also in AbstractChartPanel specializations such as competitor charts --- .../gwt/ui/shared/charts/AbstractChartPanel.java | 3 +-- .../sap/sailing/gwt/ui/shared/charts/RaceChart.java | 13 ++++--------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/AbstractChartPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/AbstractChartPanel.java index 5083b037901..110255650c1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/AbstractChartPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/AbstractChartPanel.java @@ -120,7 +120,6 @@ implements CompetitorSelectionChangeListener, RequiresResize { .setMarginRight(65) .setBorderColor(new Color("#A6A6A6")) .setBorderWidth(1) -// .setBackgroundColor(new Color("#C6C6C6")) .setChartSubtitle(new ChartSubtitle().setText(stringMessages.clickAndDragToZoomIn())) .setLinePlotOptions(new LinePlotOptions().setLineWidth(LINE_WIDTH).setMarker(new Marker().setEnabled(false).setHoverState( new Marker().setEnabled(true).setRadius(4))).setShadow(false) @@ -259,7 +258,7 @@ implements CompetitorSelectionChangeListener, RequiresResize { chart.getXAxis().setMax(maxTimepoint.getTime()); drawChartData(); - chart.hideLoading(); + hideLoading(); } }); asyncActionsExecutor.execute(getCompetitorsRaceDataAction); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/RaceChart.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/RaceChart.java index 2c547fb58ca..25dac11633d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/RaceChart.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/RaceChart.java @@ -107,7 +107,7 @@ public abstract class RaceChart extends SimplePanel implements RaceTimesInfoProv } protected void hideLoading() { - if(timer.getPlayMode() != PlayModes.Live) { + if (timer.getPlayMode() != PlayModes.Live) { chart.hideLoading(); } isLoading = false; @@ -134,14 +134,9 @@ public abstract class RaceChart extends SimplePanel implements RaceTimesInfoProv } protected boolean onClick(ChartClickEvent chartClickEvent) { - if(!isLoading && !isZoomed) { - // when the user zooms into the chart first a AxisSetExtremesEvent is sent and a ChartClickEvent afterwards -// if (ignoreClickOnce) { -// ignoreClickOnce = false; -// } else { - timer.setPlayMode(PlayModes.Replay); - timer.setTime(chartClickEvent.getXAxisValueAsLong()); -// } + if (!isLoading && !isZoomed) { + timer.setPlayMode(PlayModes.Replay); + timer.setTime(chartClickEvent.getXAxisValueAsLong()); } return true; } From 70511e4de887b83d4b6f227042383e608c622c88 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 26 May 2012 14:56:49 +0200 Subject: [PATCH 15/32] changed activemq URL to use 0.0.0.0 instead of localhost to also allow for remote connections --- java/com.sap.sailing.feature.p2build/raceanalysis.product | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.feature.p2build/raceanalysis.product b/java/com.sap.sailing.feature.p2build/raceanalysis.product index eeae58e0148..b512bd4c1aa 100644 --- a/java/com.sap.sailing.feature.p2build/raceanalysis.product +++ b/java/com.sap.sailing.feature.p2build/raceanalysis.product @@ -44,7 +44,7 @@ - + From 1e308e8b5cc3ae5261b32bb5eb98f24eb4ff00d4 Mon Sep 17 00:00:00 2001 From: fmittag Date: Sat, 26 May 2012 15:26:11 +0200 Subject: [PATCH 16/32] fix display bug in headline of raceboard if you start the raceboard from the spectator view --- java/com.sap.sailing.gwt.ui/RaceBoard.css | 13 ++++++++++++- .../gwt/ui/raceboard/GlobalNavigationPanel.java | 12 ++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/RaceBoard.css b/java/com.sap.sailing.gwt.ui/RaceBoard.css index 42633a0a946..94ceca22f99 100644 --- a/java/com.sap.sailing.gwt.ui/RaceBoard.css +++ b/java/com.sap.sailing.gwt.ui/RaceBoard.css @@ -142,7 +142,18 @@ input.opencoloumn { } .globalNavigation-leaderBoardGroup { - background-color: gray; + background: url(images/globalNavigation-home_bg.png) 5px center no-repeat #7c7b7c; + border-radius: 0px 0px 4px 4px; + -moz-border-radius: 0px 0px 4px 4px; + -webkit-border-radius: 0px 0px 4px 4px; + margin: 0 10px 0 0; + padding: 5px 6px 5px 25px; + float: left; +} + +.globalNavigation-leaderBoardGroup a { + color: #fff; + text-decoration: none; } .raceBoardNavigation { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/GlobalNavigationPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/GlobalNavigationPanel.java index 80bed38226f..608b8055f62 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/GlobalNavigationPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/GlobalNavigationPanel.java @@ -34,12 +34,12 @@ public class GlobalNavigationPanel extends FlowPanel { String homeLink = spectatorViewLink; if(showHomeNavigation) { - addNavigationLink(stringMessages.home(), homeLink, "home"); - } - - if (leaderboardGroupName != null && !leaderboardGroupName.isEmpty()) { - String leaderBoardGroupLink = spectatorViewLink + "?leaderboardGroupName=" + leaderboardGroupName; - addNavigationLink(leaderboardGroupName, leaderBoardGroupLink, "leaderBoardGroup"); + if (leaderboardGroupName != null && !leaderboardGroupName.isEmpty()) { + String leaderBoardGroupLink = spectatorViewLink + "?leaderboardGroupName=" + leaderboardGroupName; + addNavigationLink(leaderboardGroupName, leaderBoardGroupLink, "leaderBoardGroup"); + } else { + addNavigationLink(stringMessages.home(), homeLink, "home"); + } } if (leaderboardName != null && !leaderboardName.isEmpty()) { From 9a87148983289fcef2b80bb4a5ff1e9036862166 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 26 May 2012 19:37:44 +0200 Subject: [PATCH 17/32] addressing bug 612: JSON/REST export of leaderboard data --- .../sap/sailing/domain/base/RaceColumn.java | 3 +- .../com/sap/sailing/domain/base/Series.java | 3 + .../sailing/domain/base/impl/SeriesImpl.java | 6 +- .../leaderboard/impl/RaceColumnImpl.java | 11 ++- .../SailingServer (No Proxy).launch | 2 +- java/com.sap.sailing.server/WEB-INF/web.xml | 18 ++++ .../server/impl/LeaderboardJsonExport.java | 92 +++++++++++++++++++ .../sailing/server/impl/ListLeaderboards.java | 28 ++++++ 8 files changed, 159 insertions(+), 4 deletions(-) create mode 100755 java/com.sap.sailing.server/src/com/sap/sailing/server/impl/LeaderboardJsonExport.java create mode 100755 java/com.sap.sailing.server/src/com/sap/sailing/server/impl/ListLeaderboards.java diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java index 8858280caf6..bed5701d6f7 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumn.java @@ -23,7 +23,8 @@ import com.sap.sailing.domain.tracking.TrackedRace; */ public interface RaceColumn extends Named { /** - * @return the fleets for each of which this column has a single race and therefore optionally a {@link TrackedRace} + * @return the fleets for each of which this column has a single race and therefore optionally a {@link TrackedRace}, in + * ascending order; best fleets first */ Iterable getFleets(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java index 798eabf0f8d..0763d2c4d9d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java @@ -15,6 +15,9 @@ import com.sap.sailing.domain.common.Named; * */ public interface Series extends Named { + /** + * Returns the fleets of this series, on ascending order, better fleets first. + */ Iterable getFleets(); /** diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SeriesImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SeriesImpl.java index adb79e8f521..b9d3c5440e4 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SeriesImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SeriesImpl.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.base.impl; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -13,6 +14,7 @@ import com.sap.sailing.domain.common.impl.NamedImpl; public class SeriesImpl extends NamedImpl implements Series { private static final long serialVersionUID = -1640404303144907381L; private final Map fleetsByName; + private final List fleetsInAscendingOrder; private final Iterable raceColumns; private boolean isMedal; @@ -22,6 +24,8 @@ public class SeriesImpl extends NamedImpl implements Series { for (Fleet fleet : fleets) { this.fleetsByName.put(fleet.getName(), fleet); } + fleetsInAscendingOrder = new ArrayList(fleetsByName.values()); + Collections.sort(fleetsInAscendingOrder); List myRaceColumns = new ArrayList(); for (String raceColumnName : raceColumnNames) { RaceColumnInSeriesImpl raceColumn = new RaceColumnInSeriesImpl(raceColumnName, this); @@ -32,7 +36,7 @@ public class SeriesImpl extends NamedImpl implements Series { } public Iterable getFleets() { - return fleetsByName.values(); + return fleetsInAscendingOrder; } @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RaceColumnImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RaceColumnImpl.java index f4051d853c0..a051df320a9 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RaceColumnImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RaceColumnImpl.java @@ -1,5 +1,9 @@ package com.sap.sailing.domain.leaderboard.impl; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.impl.AbstractRaceColumn; import com.sap.sailing.domain.leaderboard.FlexibleRaceColumn; @@ -17,7 +21,12 @@ public class RaceColumnImpl extends AbstractRaceColumn implements FlexibleRaceCo public RaceColumnImpl(String name, boolean medalRace, Iterable fleets) { super(name); this.medalRace = medalRace; - this.fleets = fleets; + List myFleets = new ArrayList(); + for (Fleet fleet : fleets) { + myFleets.add(fleet); + } + Collections.sort(myFleets); + this.fleets = myFleets; } @Override diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy).launch b/java/com.sap.sailing.server/SailingServer (No Proxy).launch index d203e975d89..776f66b7a4f 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy).launch @@ -24,5 +24,5 @@ - + diff --git a/java/com.sap.sailing.server/WEB-INF/web.xml b/java/com.sap.sailing.server/WEB-INF/web.xml index 25cb9aa5d97..f0f15a9d2a8 100644 --- a/java/com.sap.sailing.server/WEB-INF/web.xml +++ b/java/com.sap.sailing.server/WEB-INF/web.xml @@ -31,4 +31,22 @@ ExpeditionThroughHttpPostServlet /expedition + + + ListLeaderboards + com.sap.sailing.server.impl.ListLeaderboards + + + ListLeaderboards + /listleaderboards + + + + LeaderboardJsonExport + com.sap.sailing.server.impl.LeaderboardJsonExport + + + LeaderboardJsonExport + /leaderboard + diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/LeaderboardJsonExport.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/LeaderboardJsonExport.java new file mode 100755 index 00000000000..8f46ce787ae --- /dev/null +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/LeaderboardJsonExport.java @@ -0,0 +1,92 @@ +package com.sap.sailing.server.impl; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; +import com.sap.sailing.domain.common.NoWindException; +import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.server.Servlet; + +public class LeaderboardJsonExport extends Servlet { + private static final long serialVersionUID = -2460691283231361152L; + private static final String PARAM_NAME_LEADERBOARDNAME = "leaderboardName"; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + TimePoint timePoint = MillisecondsTimePoint.now(); + String leaderboardName = req.getParameter(PARAM_NAME_LEADERBOARDNAME); + if (leaderboardName == null) { + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Need to specify a leaderboard name using the "+ + PARAM_NAME_LEADERBOARDNAME+" parameter"); + } else { + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + if (leaderboard == null) { + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Leaderboard "+leaderboardName+" not found"); + } else { + try { + List competitorsFromBestToWorstAccordingToTotalRank = leaderboard + .getCompetitorsFromBestToWorst(timePoint); + Map> rankedCompetitorsPerColumn = new HashMap>(); + JSONObject jsonLeaderboard = new JSONObject(); + jsonLeaderboard.put("name", leaderboard.getName()); + JSONArray jsonColumnNames = new JSONArray(); + jsonLeaderboard.put("columnNames", jsonColumnNames); + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + jsonColumnNames.add(raceColumn.getName()); + } + JSONArray jsonCompetitorEntries = new JSONArray(); + jsonLeaderboard.put("competitors", jsonCompetitorEntries); + for (Competitor competitor : competitorsFromBestToWorstAccordingToTotalRank) { + JSONObject jsonCompetitor = new JSONObject(); + jsonCompetitor.put("name", competitor.getName()); + final String displayName = leaderboard.getDisplayName(competitor); + jsonCompetitor.put("displayName", displayName==null?competitor.getName():displayName); + jsonCompetitor.put("id", competitor.getId().toString()); + jsonCompetitor.put("sailID", competitor.getBoat().getSailID()); + jsonCompetitor.put("nationality", competitor.getTeam().getNationality() + .getThreeLetterIOCAcronym()); + jsonCompetitor.put("rank", + competitorsFromBestToWorstAccordingToTotalRank.indexOf(competitor) + 1); + jsonCompetitor.put("totalPoints", leaderboard.getTotalPoints(competitor, timePoint)); + jsonCompetitorEntries.add(jsonCompetitor); + JSONObject jsonRaceColumns = new JSONObject(); + jsonCompetitor.put("raceScores", jsonRaceColumns); + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + List rankedCompetitorsForColumn = rankedCompetitorsPerColumn.get(raceColumn); + if (rankedCompetitorsForColumn == null) { + rankedCompetitorsForColumn = leaderboard.getCompetitorsFromBestToWorst(raceColumn, timePoint); + rankedCompetitorsPerColumn.put(raceColumn, rankedCompetitorsForColumn); + } + JSONObject jsonEntry = new JSONObject(); + jsonRaceColumns.put(raceColumn.getName(), jsonEntry); + final Fleet fleetOfCompetitor = raceColumn.getFleetOfCompetitor(competitor); + jsonEntry.put("fleet", fleetOfCompetitor==null?"":fleetOfCompetitor.getName()); + jsonEntry.put("netPoints", leaderboard.getNetPoints(competitor, raceColumn, timePoint)); + jsonEntry.put("totalPoints", leaderboard.getTotalPoints(competitor, raceColumn, timePoint)); + jsonEntry.put("maxPointsReason", leaderboard.getMaxPointsReason(competitor, raceColumn, timePoint)); + jsonEntry.put("rank", rankedCompetitorsForColumn.indexOf(competitor)+1); + jsonEntry.put("isDiscarded", leaderboard.isDiscarded(competitor, raceColumn, timePoint)); + } + } + jsonLeaderboard.writeJSONString(resp.getWriter()); + } catch (NoWindException e) { + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); + } + } + } + } +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/ListLeaderboards.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/ListLeaderboards.java new file mode 100755 index 00000000000..c65fb6b0eb8 --- /dev/null +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/ListLeaderboards.java @@ -0,0 +1,28 @@ +package com.sap.sailing.server.impl; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.json.simple.JSONArray; + +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.server.Servlet; + +public class ListLeaderboards extends Servlet { + private static final long serialVersionUID = -2193421590275280102L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + JSONArray jsonLeaderboards = new JSONArray(); + Map leaderboards = getService().getLeaderboards(); + for (String leaderboardName : leaderboards.keySet()) { + jsonLeaderboards.add(leaderboardName); + } + jsonLeaderboards.writeJSONString(resp.getWriter()); + } + +} From 0b35c6df2ce066a0bafc015292784ee528cb0e12 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 26 May 2012 22:03:33 +0200 Subject: [PATCH 18/32] fixing bug 681: competitor chart now reliably shows data also for selection changed while invisible --- .../ui/shared/charts/AbstractChartPanel.java | 118 ++++++++++-------- 1 file changed, 69 insertions(+), 49 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/AbstractChartPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/AbstractChartPanel.java index 110255650c1..aeb57d5d35d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/AbstractChartPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/charts/AbstractChartPanel.java @@ -79,6 +79,12 @@ implements CompetitorSelectionChangeListener, RequiresResize { private long stepSize = 5000; private DetailType dataToShow; private final CompetitorSelectionProvider competitorSelectionProvider; + + /** + * When the chart is not visible and the competitor selection changes, no loading is performed. However, in this case + * we need to remember that loading will be necessary as soon as the chart becomes visible. + */ + private boolean needToLoadWhenMadeVisible; public AbstractChartPanel(SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, CompetitorSelectionProvider competitorSelectionProvider, RaceSelectionProvider raceSelectionProvider, @@ -104,6 +110,14 @@ implements CompetitorSelectionChangeListener, RequiresResize { timer.addTimeListener(this); timeZoomProvider.addTimeZoomChangeListener(this); } + + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + if (needToLoadWhenMadeVisible) { + loadData(/* showBusyIndicator */ true); + } + } /** * Creates a new chart for the given {@link DetailType} dataToShow and also @@ -210,60 +224,70 @@ implements CompetitorSelectionChangeListener, RequiresResize { * @param showBusyIndicator If true is the busy indicator shown while loading the data from the server. */ protected void loadData(boolean showBusyIndicator) { - if (needsDataLoading()) { - if (showBusyIndicator) { - setWidget(chart); - showLoading("Loading competitor data..."); - } - if (chartData == null || chartData.getDetailType() != getDataToShow()) { - chartData = new MultiCompetitorRaceDataDTO(getDataToShow()); - } - -// Date toDate = new Date(System.currentTimeMillis() - timer.getLivePlayDelayInMillis()); - final ArrayList> dataQuery = new ArrayList>(); - for (CompetitorDTO competitor : getVisibleCompetitors()) { - Date chartDataDateOfNewestData = chartData.getDateOfNewestData(); - Date competitorDateOfNewestData = chartData.contains(competitor) ? chartData.getCompetitorData(competitor).getDateOfNewestData() : null; - if (!chartData.contains(competitor)) { - dataQuery.add(new Pair(new Date(0), competitor)); - } else if (competitorDateOfNewestData.before(chartDataDateOfNewestData) || competitorDateOfNewestData.before(maxTimepoint)) { - dataQuery.add(new Pair(new Date(competitorDateOfNewestData.getTime() + getStepSize()), competitor)); + if (isVisible()) { + if (hasVisibleCompetitors()) { + needToLoadWhenMadeVisible = false; // we're loading it now + if (showBusyIndicator) { + setWidget(chart); + showLoading("Loading competitor data..."); + } + if (chartData == null || chartData.getDetailType() != getDataToShow()) { + chartData = new MultiCompetitorRaceDataDTO(getDataToShow()); } - } - - GetCompetitorsRaceDataAction getCompetitorsRaceDataAction = new GetCompetitorsRaceDataAction(sailingService, - selectedRaceIdentifier, dataQuery, maxTimepoint, getStepSize(), getDataToShow(), - new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError(getStringMessages().failedToLoadRaceData() + ": " + caught.toString(), + // Date toDate = new Date(System.currentTimeMillis() - timer.getLivePlayDelayInMillis()); + final ArrayList> dataQuery = new ArrayList>(); + for (CompetitorDTO competitor : getVisibleCompetitors()) { + Date chartDataDateOfNewestData = chartData.getDateOfNewestData(); + Date competitorDateOfNewestData = chartData.contains(competitor) ? chartData.getCompetitorData( + competitor).getDateOfNewestData() : null; + if (!chartData.contains(competitor)) { + dataQuery.add(new Pair(new Date(0), competitor)); + } else if (competitorDateOfNewestData.before(chartDataDateOfNewestData) + || competitorDateOfNewestData.before(maxTimepoint)) { + dataQuery.add(new Pair(new Date(competitorDateOfNewestData.getTime() + + getStepSize()), competitor)); + } + } + + GetCompetitorsRaceDataAction getCompetitorsRaceDataAction = new GetCompetitorsRaceDataAction( + sailingService, selectedRaceIdentifier, dataQuery, maxTimepoint, getStepSize(), + getDataToShow(), new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError( + getStringMessages().failedToLoadRaceData() + ": " + caught.toString(), timer.getPlayMode() == PlayModes.Live); hideLoading(); - } + } - @Override - public void onSuccess(MultiCompetitorRaceDataDTO result) { - if (result != null) { - for (CompetitorRaceDataDTO competitorData : result.getAllRaceData()) { - if (chartData.contains(competitorData.getCompetitor())) { - chartData.addCompetitorRaceData(competitorData); - chartData.setCompetitorMarkPassingsData(competitorData); - } else { - chartData.setCompetitorData(competitorData.getCompetitor(), competitorData); + @Override + public void onSuccess(MultiCompetitorRaceDataDTO result) { + if (result != null) { + for (CompetitorRaceDataDTO competitorData : result.getAllRaceData()) { + if (chartData.contains(competitorData.getCompetitor())) { + chartData.addCompetitorRaceData(competitorData); + chartData.setCompetitorMarkPassingsData(competitorData); + } else { + chartData.setCompetitorData(competitorData.getCompetitor(), competitorData); + } } } - } - chart.getXAxis().setMin(minTimepoint.getTime()); - chart.getXAxis().setMax(maxTimepoint.getTime()); + chart.getXAxis().setMin(minTimepoint.getTime()); + chart.getXAxis().setMax(maxTimepoint.getTime()); - drawChartData(); - hideLoading(); - } - }); - asyncActionsExecutor.execute(getCompetitorsRaceDataAction); + drawChartData(); + hideLoading(); + } + }); + asyncActionsExecutor.execute(getCompetitorsRaceDataAction); + } else { + setWidget(noCompetitorsSelectedLabel); + } } else { - setWidget(noCompetitorsSelectedLabel); + // not visible; don't load data but remember that data needs to be loaded as soon as the chart becomes visible + needToLoadWhenMadeVisible = true; } } @@ -569,10 +593,6 @@ implements CompetitorSelectionChangeListener, RequiresResize { } } - private boolean needsDataLoading() { - return hasVisibleCompetitors() && isVisible(); - } - @Override public void onResize() { if(getChartData() != null) { From d417af0aa9e696311054f979ba26337e981bcef3 Mon Sep 17 00:00:00 2001 From: fmittag Date: Sun, 27 May 2012 11:33:43 +0200 Subject: [PATCH 19/32] disabled geocoder cause of NPE in getLeaderbordGroup() --- .../java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index c1231aea193..bf5974ddef3 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -1772,7 +1772,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS groupDTO.name = leaderboardGroup.getName(); groupDTO.description = leaderboardGroup.getDescription(); for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { - groupDTO.leaderboards.add(createStrippedLeaderboardDTO(leaderboard, true)); + groupDTO.leaderboards.add(createStrippedLeaderboardDTO(leaderboard, false)); } return groupDTO; } From ce674661a956a381a83b8b4fb8de8c833d08e757 Mon Sep 17 00:00:00 2001 From: fmittag Date: Sun, 27 May 2012 16:04:52 +0200 Subject: [PATCH 20/32] moved the settings buttons close to the toggle buttons of the components --- java/com.sap.sailing.gwt.ui/RaceBoard.css | 17 ++++- .../images/settings_new.png | Bin 0 -> 743 bytes .../gwt/ui/raceboard/RaceBoardEntryPoint.java | 2 - .../gwt/ui/raceboard/RaceBoardPanel.java | 62 +++++++----------- .../ui/shared/controls/slider/SliderBar.java | 6 +- .../gwt/ui/shared/controls/slider/slider.gif | Bin 596 -> 0 bytes .../ui/shared/controls/slider/slider_blue.png | Bin 0 -> 422 bytes 7 files changed, 41 insertions(+), 46 deletions(-) create mode 100644 java/com.sap.sailing.gwt.ui/images/settings_new.png delete mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/controls/slider/slider.gif create mode 100644 java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/controls/slider/slider_blue.png diff --git a/java/com.sap.sailing.gwt.ui/RaceBoard.css b/java/com.sap.sailing.gwt.ui/RaceBoard.css index 94ceca22f99..a093f67a535 100644 --- a/java/com.sap.sailing.gwt.ui/RaceBoard.css +++ b/java/com.sap.sailing.gwt.ui/RaceBoard.css @@ -210,16 +210,27 @@ input.opencoloumn { margin: 9px 12px 0 0; } +.raceBoardNavigation-settingsButton { + background: url(images/settings_new.png) center no-repeat; + width: 27px; + height: 23px; + margin: 0 5px 0 0; +} + +.raceBoardNavigation-settingsButton:hover { + background: url(images/settings_new.png) center no-repeat; +} .raceBoardNavigation-innerElement { background: url("images/btn-cta-orangeleft.png") repeat-x scroll center 0 transparent; border: medium none; - border-radius: 3px 3px 3px 3px; - color: #FFFFFF; + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; + color: #FFFFFF; cursor: pointer; font-family: UbuntuBold,Verdana,Arial,sans-serif; font-size: 14px; - margin: 0 0 0 5px; + margin: 0 0 0 0; padding: 2px 7px 2px 3px; } .raceBoardNavigation-innerElement:hover { diff --git a/java/com.sap.sailing.gwt.ui/images/settings_new.png b/java/com.sap.sailing.gwt.ui/images/settings_new.png new file mode 100644 index 0000000000000000000000000000000000000000..bffe7fc9bdc32fa1415752832204a96506dd4fb9 GIT binary patch literal 743 zcmV?P)r+;i^l+_K*bdi4vdU9nDwG4y?p7&6^NOefYzuze z4S^2~_E=xPUe&P8a=;wJGGEJq%cUa!TXg-NSBgLx386>ZMF~B7}};v zM3s(;Dh z-d#27rfFcMIGW#QtQqIx^4vtzG%cLx!~Tw`Z>#9@cV>BOwBHxtUA2u36HE z>cNcGkNdM+HYMOa^2;2({w-*l-fcw$ndt5{sm@Oc4>Fv?-N+H@!2fj5y|lhBl0pO$rW2 zi)-X))DcpBo~;(DfvacraJ)>ESiL=OrVbxo);odm{;MiO{BjSc> zCUS%saDxB< literal 0 HcmV?d00001 diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java index 8b3c62b6f8c..b93fbd3d7e0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java @@ -183,9 +183,7 @@ public class RaceBoardEntryPoint extends AbstractEntryPoint { FlowPanel toolbarPanel = new FlowPanel(); - //TODO Quickfix for touch devices toolbarPanel.add(raceBoardPanel.getNavigationWidget()); - toolbarPanel.add(raceBoardPanel.getSettingsWidget()); FlowPanel logoAndTitlePanel = createLogoAndTitlePanel(raceBoardPanel); FlowPanel timePanel = createTimePanel(raceBoardPanel); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java index 2d4344ec631..cee8672da8a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java @@ -17,7 +17,6 @@ import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FormPanel; -import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.MenuBar; import com.google.gwt.user.client.ui.ToggleButton; import com.google.gwt.user.client.ui.Widget; @@ -175,23 +174,10 @@ public class RaceBoardPanel extends FormPanel implements RegattaDisplayer, RaceS mainPanel.add(componentViewer.getViewerWidget()); } - settingsPanel = new FlowPanel(); - settingsPanel.addStyleName("raceBoardNavigation-settingsButtonPanel"); - Label settingsLabel = new Label("Settings: "); - settingsLabel.addStyleName("raceBoardNavigation-settingsLabel"); - settingsLabel.getElement().getStyle().setFloat(Style.Float.LEFT); - settingsLabel.getElement().getStyle().setPadding(3, Style.Unit.PX); - settingsPanel.add(settingsLabel); - - addSettingsMenuButton(settingsPanel, leaderboardPanel); - addSettingsMenuButton(settingsPanel, raceMap); - addSettingsMenuButton(settingsPanel, windChart); - addSettingsMenuButton(settingsPanel, competitorChart); - - addComponentAsCheckboxToNavigationMenu(leaderboardAndMapViewer, leaderboardPanel); - addComponentAsCheckboxToNavigationMenu(leaderboardAndMapViewer, windChart); - addComponentAsCheckboxToNavigationMenu(leaderboardAndMapViewer, competitorChart); - + addComponentToNavigationMenu(leaderboardAndMapViewer, leaderboardPanel, true); + addComponentToNavigationMenu(leaderboardAndMapViewer, windChart, true); + addComponentToNavigationMenu(leaderboardAndMapViewer, competitorChart, true); + addComponentToNavigationMenu(leaderboardAndMapViewer, raceMap, false); } @SuppressWarnings("unused") @@ -205,23 +191,6 @@ public class RaceBoardPanel extends FormPanel implements RegattaDisplayer, RaceS } } - private void addSettingsMenuButton(FlowPanel settingsPanel, final Component component) { - if(component.hasSettings()) { - Button settingsButton = new Button(component.getLocalizedShortName()); - settingsButton.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - new SettingsDialog(component, stringMessages).show(); - } - }); - settingsButton.addStyleName("raceBoardNavigation-settingsButton"); - settingsButton.getElement().getStyle().setFloat(Style.Float.LEFT); - settingsButton.getElement().getStyle().setPadding(3, Style.Unit.PX); - - settingsPanel.add(settingsButton); - } - } - private LeaderboardPanel createLeaderboardPanel(String leaderboardName, String leaderboardGroupName) { LeaderboardSettings leaderBoardSettings = LeaderboardSettingsFactory.getInstance() .createNewSettingsForPlayMode(timer.getPlayMode(), /* nameOfRaceToSort */ @@ -232,11 +201,12 @@ public class RaceBoardPanel extends FormPanel implements RegattaDisplayer, RaceS userAgentType); } - private void addComponentAsCheckboxToNavigationMenu(final ComponentViewer componentViewer, - final Component component) { + private void addComponentToNavigationMenu(final ComponentViewer componentViewer, + final Component component, boolean withCheckbox) { final CheckBox checkBox= new CheckBox(component.getLocalizedShortName()); checkBox.getElement().getStyle().setFloat(Style.Float.LEFT); - + + checkBox.setEnabled(withCheckbox); checkBox.setValue(component.isVisible()); checkBox.setTitle(stringMessages.showHideComponent(component.getLocalizedShortName())); checkBox.addStyleName("raceBoardNavigation-innerElement"); @@ -260,6 +230,22 @@ public class RaceBoardPanel extends FormPanel implements RegattaDisplayer, RaceS }); componentsNavigationPanel.add(checkBox); + + if(component.hasSettings()) { + Button settingsButton = new Button(""); + settingsButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + new SettingsDialog(component, stringMessages).show(); + } + }); + settingsButton.addStyleName("raceBoardNavigation-settingsButton"); + settingsButton.getElement().getStyle().setFloat(Style.Float.LEFT); + settingsButton.setTitle(stringMessages.settingsForComponent(component.getLocalizedShortName())); + + componentsNavigationPanel.add(settingsButton); + } + } public void addComponentAsToogleButtonToNavigationMenu(final ComponentViewer componentViewer, diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/controls/slider/SliderBar.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/controls/slider/SliderBar.java index d52af6c4db7..a0a9fdc12b3 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/controls/slider/SliderBar.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/controls/slider/SliderBar.java @@ -103,7 +103,7 @@ public class SliderBar extends FocusPanel implements RequiresResize, HasValueuA`{Ax4dIgMd#$&zL^b^=C#jSHgVae`J48wU$<`k z`gI#Ntlt0v8#inOflVN=83=an*trvgckSE-0=q$A&-(o*_UzfScP|j_-FoEgwxeec zgTN6WIC}Kxv134V?8Nco$4?yJclz>)6DQ6B!MU^N&Ye3Cf#-qX!i5XxFI>EE@#4ix zmo8ntbm_+R>o>070D_w!a0>)M;P&lXx9{A(eFp^Yg226dj~;`-69|0r`7kDnm$3kZJy{sTmRfauTP zzd-c&@4vtQ|Nmc2F;M);!pOx?&!7X02?kJ{FtBfIsBdawYi?`eU|?+TVCd^^>trzR zZ=U38p*@weFUZYON3oAdnjt>e!%A0Cgn>mqGaUE#eR;bU*CB6)8^N|djIiK-;u+2lyS*J@JyXH%nn z9Zl3^1kRo*XjEEqtdmcWt-+&s+3CrOrU4}r0u)@OOyU*^Y+QKga0_#NP{R+0Nl)5X KdL&qx7_0#lrf#GF diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/controls/slider/slider_blue.png b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/controls/slider/slider_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..7e7cdb9f205ae944d5734ab3c82be3f47f47612a GIT binary patch literal 422 zcmV;X0a^ZuP)JNk_VF}!tfKHHRWMg+?;uS>E#K;Z|Odftkpu8nEo1(x@VPwPz8D?QrC!%O# z5|&`V2Ed`n$e07PjTx>96gt3AGGOB3#i|Jyq6|#@!r(YWwkZl4N;m;>D8e+wGK&z< z1da;kD4?r&m=}E$vti;9C}fe4$EyhxK>vSyW%&R7%MB*5(}eNcf*y)YKoc^Vgv5!` z#Kb2AO2{5eOyCsFN|Yv$6G0X*G2@6EoK6G=7z-mC2gARwpGeTg$N&&v0I^t9<;jR$ Q-v9sr07*qoM6N<$f^3AP#sB~S literal 0 HcmV?d00001 From 975a6e25e73c31eae98c1990c9d5ab1060b1baa2 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sun, 27 May 2012 21:55:52 +0200 Subject: [PATCH 21/32] fixing bug 683; added two tests in CourseTest which first reproduced the problem which then got fixed by this. --- .../sap/sailing/domain/test/CourseTest.java | 44 +++++++++++++++++++ .../sailing/domain/base/impl/CourseImpl.java | 18 +++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java index 9cf27561c61..5bb04aa475f 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseTest.java @@ -1,8 +1,10 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -80,4 +82,46 @@ public class CourseTest { assertEquals(0, Util.size(course.getWaypoints())); assertEquals(0, Util.size(course.getLegs())); } + + @Test + public void testInsertWaypointToCourseWithTwoWaypoints() { + List waypoints = new ArrayList(); + final WaypointImpl wp1 = new WaypointImpl(new BuoyImpl("Test Buoy 1")); + waypoints.add(wp1); + final WaypointImpl wp2 = new WaypointImpl(new BuoyImpl("Test Buoy 2")); + waypoints.add(wp2); + Course course = new CourseImpl("Test Course", waypoints); + assertEquals(2, Util.size(course.getWaypoints())); + assertEquals(1, Util.size(course.getLegs())); + final WaypointImpl wp1_5 = new WaypointImpl(new BuoyImpl("Test Buoy 1.5")); + course.addWaypoint(1, wp1_5); + assertEquals(3, Util.size(course.getWaypoints())); + assertEquals(2, Util.size(course.getLegs())); + assertTrue(Util.equals(Arrays.asList(new Waypoint[] { wp1, wp1_5, wp2 }), course.getWaypoints())); + assertEquals(0, course.getIndexOfWaypoint(wp1)); + assertEquals(1, course.getIndexOfWaypoint(wp1_5)); + assertEquals(2, course.getIndexOfWaypoint(wp2)); + } + + @Test + public void testRemovetWaypointFromCourseWithThreeWaypoints() { + List waypoints = new ArrayList(); + final WaypointImpl wp1 = new WaypointImpl(new BuoyImpl("Test Buoy 1")); + waypoints.add(wp1); + final WaypointImpl wp2 = new WaypointImpl(new BuoyImpl("Test Buoy 2")); + waypoints.add(wp2); + final WaypointImpl wp3 = new WaypointImpl(new BuoyImpl("Test Buoy 3")); + waypoints.add(wp3); + Course course = new CourseImpl("Test Course", waypoints); + assertEquals(3, Util.size(course.getWaypoints())); + assertEquals(2, Util.size(course.getLegs())); + course.removeWaypoint(1); + assertEquals(2, Util.size(course.getWaypoints())); + assertEquals(1, Util.size(course.getLegs())); + assertTrue(Util.equals(Arrays.asList(new Waypoint[] { wp1, wp3 }), course.getWaypoints())); + assertEquals(0, course.getIndexOfWaypoint(wp1)); + assertEquals(-1, course.getIndexOfWaypoint(wp2)); + assertEquals(1, course.getIndexOfWaypoint(wp3)); + } + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java index a46ed7dc970..2724ce1f4aa 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/CourseImpl.java @@ -87,6 +87,14 @@ public class CourseImpl extends NamedImpl implements Course { @Override public synchronized void addWaypoint(int zeroBasedPosition, Waypoint waypointToAdd) { waypoints.add(zeroBasedPosition, waypointToAdd); + Map updatesToWaypointIndexes = new HashMap(); + updatesToWaypointIndexes.put(waypointToAdd, zeroBasedPosition); + for (Map.Entry e : waypointIndexes.entrySet()) { + if (e.getValue() >= zeroBasedPosition) { + updatesToWaypointIndexes.put(e.getKey(), e.getValue()+1); + } + } + waypointIndexes.putAll(updatesToWaypointIndexes); int legStartWaypointIndex; if (zeroBasedPosition == waypoints.size()-1) { // added to end legStartWaypointIndex = zeroBasedPosition-1; @@ -104,6 +112,14 @@ public class CourseImpl extends NamedImpl implements Course { if (zeroBasedPosition >= 0) { boolean isLast = zeroBasedPosition == waypoints.size()-1; Waypoint removedWaypoint = waypoints.remove(zeroBasedPosition); + waypointIndexes.remove(removedWaypoint); + Map updatesToWaypointIndexes = new HashMap(); + for (Map.Entry e : waypointIndexes.entrySet()) { + if (e.getValue() > zeroBasedPosition) { // only > because the entry with == was just removed + updatesToWaypointIndexes.put(e.getKey(), e.getValue()-1); + } + } + waypointIndexes.putAll(updatesToWaypointIndexes); if (isLast) { if (waypoints.size() > 0) { // if we had only one waypoint, we didn't have any legs // last waypoint was removed; remove last leg @@ -167,7 +183,7 @@ public class CourseImpl extends NamedImpl implements Course { } @Override - public int getIndexOfWaypoint(Waypoint waypoint) { + public synchronized int getIndexOfWaypoint(Waypoint waypoint) { int result = -1; Integer indexEntry = waypointIndexes.get(waypoint); if (indexEntry != null) { From 2b487ca2bff8395a04f9f9313c598cae26dffc53 Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Mon, 28 May 2012 10:18:18 +0200 Subject: [PATCH 22/32] Set hover state for raceBoardNavigation-settingsButton --- java/com.sap.sailing.gwt.ui/RaceBoard.css | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/RaceBoard.css b/java/com.sap.sailing.gwt.ui/RaceBoard.css index a093f67a535..1c240905378 100644 --- a/java/com.sap.sailing.gwt.ui/RaceBoard.css +++ b/java/com.sap.sailing.gwt.ui/RaceBoard.css @@ -211,14 +211,21 @@ input.opencoloumn { } .raceBoardNavigation-settingsButton { - background: url(images/settings_new.png) center no-repeat; + background: url(images/settings_white.png), url(images/btn-cta-orangeleft.png); + background-position: center, center 0; + background-repeat: no-repeat, repeat-x; width: 27px; height: 23px; - margin: 0 5px 0 0; + margin: 0 5px 0 1px; + -webkit-border-radius: 0px 3px 3px 0px; + border-radius: 0px 3px 3px 0px; } .raceBoardNavigation-settingsButton:hover { - background: url(images/settings_new.png) center no-repeat; + background-image: url(images/settings_white.png), url(images/btn-cta-orangeleft.png); + background-position: center, center -30px; + background-repeat: no-repeat, repeat-x; + cursor: pointer; } .raceBoardNavigation-innerElement { From 8e7a8d25ca650ac4b2798fff2d4692c907978d61 Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Mon, 28 May 2012 10:20:26 +0200 Subject: [PATCH 23/32] add new variant of settings wheel, in white color --- .../images/settings_white.png | Bin 0 -> 3051 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 java/com.sap.sailing.gwt.ui/images/settings_white.png diff --git a/java/com.sap.sailing.gwt.ui/images/settings_white.png b/java/com.sap.sailing.gwt.ui/images/settings_white.png new file mode 100755 index 0000000000000000000000000000000000000000..a2f50722abfb748e9b47b166f9125f95da6c5e3a GIT binary patch literal 3051 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 literal 0 HcmV?d00001 From 596b9c71c99ab7699753095a52862424e5fd5483 Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Mon, 28 May 2012 10:31:31 +0200 Subject: [PATCH 24/32] Change styles for titleLabel Correct position of the inner text element --- java/com.sap.sailing.gwt.ui/CommonControls.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/CommonControls.css b/java/com.sap.sailing.gwt.ui/CommonControls.css index b45c83d2c72..ef2ff673468 100644 --- a/java/com.sap.sailing.gwt.ui/CommonControls.css +++ b/java/com.sap.sailing.gwt.ui/CommonControls.css @@ -158,8 +158,8 @@ .titleLabel { background: url(images/titleLabelInner.png) left center no-repeat; - height: 68px; - padding: 0 0 0 130px; + height: 26px; + padding: 41px 7px 0 130px; } From 8d6d359a78ab22c400ba7f5043330b987d0a6c76 Mon Sep 17 00:00:00 2001 From: fmittag Date: Mon, 28 May 2012 14:28:10 +0200 Subject: [PATCH 25/32] Added a filter for mark positions with a 0,0 lat/lon position Such positions are most probably wrong and can cause strange positioning and drawing on the map --- .../domain/tractracadapter/impl/MarkPositionReceiver.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPositionReceiver.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPositionReceiver.java index 88e6149cba5..4701a7e5c8b 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPositionReceiver.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPositionReceiver.java @@ -111,7 +111,12 @@ public class MarkPositionReceiver extends AbstractReceiverWithQueue Date: Mon, 28 May 2012 15:42:08 +0200 Subject: [PATCH 26/32] reverted last fix for filtering marks with 0/0 lat lon --- .../domain/tractracadapter/impl/MarkPositionReceiver.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPositionReceiver.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPositionReceiver.java index 4701a7e5c8b..88e6149cba5 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPositionReceiver.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPositionReceiver.java @@ -111,12 +111,7 @@ public class MarkPositionReceiver extends AbstractReceiverWithQueue Date: Mon, 28 May 2012 21:11:18 +0200 Subject: [PATCH 27/32] synchronize access to QuadTree because it's not thread safe --- .../META-INF/MANIFEST.MF | 3 +- .../domain/common/AbstractPosition.java | 9 ++-- .../common/quadtree/impl/QuadTreeNode.java | 8 ++- .../sap/sailing/domain/test/QuadTreeTest.java | 49 +++++++++++++++++++ .../geocoding/impl/ReverseGeocoderImpl.java | 12 +++-- 5 files changed, 69 insertions(+), 12 deletions(-) diff --git a/java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF index 83d845f6947..359e07e54bd 100755 --- a/java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF @@ -7,4 +7,5 @@ Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Export-Package: com.sap.sailing.domain.common, com.sap.sailing.domain.common.impl, - com.sap.sailing.domain.common.quadtree + com.sap.sailing.domain.common.quadtree, + com.sap.sailing.domain.common.quadtree.impl;x-friends:="com.sap.sailing.domain.test" diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractPosition.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractPosition.java index fe458483bbb..82c85f99dd5 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractPosition.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractPosition.java @@ -12,9 +12,12 @@ public class AbstractPosition implements Position { } public boolean equals(Object o) { - return o instanceof Position && - getLatRad() == ((Position) o).getLatRad() && - getLngRad() == ((Position) o).getLngRad(); + if (o == null) { + return false; + } else { + return o instanceof Position && getLatRad() == ((Position) o).getLatRad() + && getLngRad() == ((Position) o).getLngRad(); + } } @Override diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/quadtree/impl/QuadTreeNode.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/quadtree/impl/QuadTreeNode.java index 1de0b986ff7..ee6229d64a6 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/quadtree/impl/QuadTreeNode.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/quadtree/impl/QuadTreeNode.java @@ -110,7 +110,7 @@ public class QuadTreeNode implements Serializable { * into the children. */ @SuppressWarnings("unchecked") - protected void split() { + protected void split() { // Make sure we're bigger than the minimum, if we care, if (minSize != NO_MIN_SIZE) { if (Math.abs(bounds.getNorthEast().getLatDeg() - bounds.getSouthWest().getLatDeg()) < minSize @@ -121,7 +121,6 @@ public class QuadTreeNode implements Serializable { double nsHalf = (bounds.getNorthEast().getLatDeg() + bounds.getSouthWest().getLatDeg()) / 2.0; double ewHalf = (bounds.getNorthEast().getLngDeg() + bounds.getSouthWest().getLngDeg()) / 2.0; children = new QuadTreeNode[4]; - children[NORTHWEST] = new QuadTreeNode(new Bounds(new DegreePosition(nsHalf, bounds.getSouthWest().getLngDeg()), new DegreePosition(bounds.getNorthEast().getLatDeg(), ewHalf)), maxItems); children[NORTHEAST] = new QuadTreeNode(new Bounds(new DegreePosition(nsHalf, ewHalf), bounds.getNorthEast()), maxItems); children[SOUTHEAST] = new QuadTreeNode(new Bounds(new DegreePosition(bounds.getSouthWest().getLatDeg(), ewHalf), new DegreePosition(nsHalf, bounds.getNorthEast().getLngDeg())), maxItems); @@ -131,7 +130,6 @@ public class QuadTreeNode implements Serializable { for (Iterator> i=temp.iterator(); i.hasNext(); ) { put(i.next()); } - //items.removeAllElements(); } /** @@ -208,9 +206,9 @@ public class QuadTreeNode implements Serializable { this.allTheSamePoint = false; } } - - if (this.items.size() > maxItems && !this.allTheSamePoint) + if (this.items.size() > maxItems && !this.allTheSamePoint) { split(); + } } else { QuadTreeNode node = getChild(leaf.getPoint()); if (node != null) { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/QuadTreeTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/QuadTreeTest.java index 2577b05f536..d557698c362 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/QuadTreeTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/QuadTreeTest.java @@ -1,12 +1,14 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import org.junit.Test; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.common.quadtree.QuadTree; +import com.sap.sailing.domain.common.quadtree.impl.QuadTreeNode; public class QuadTreeTest { private class GLatLngQuadTree extends QuadTree { @@ -21,6 +23,53 @@ public class QuadTreeTest { } } + private static class QuadTreeWithPublicGetTop extends QuadTree { + private static final long serialVersionUID = -783622065160380333L; + @Override + public QuadTreeNode getTop() { + return super.getTop(); + } + } + + @Test + public void testNoNPEDuringSecondPutInSameLeaf() { + final QuadTreeWithPublicGetTop qt = new QuadTreeWithPublicGetTop(); + final Position p = new DegreePosition(0, 0); + final NullPointerException[] npe = new NullPointerException[1]; + final boolean[] stop = new boolean[1]; + Runnable r = new Runnable() { + @Override + public void run() { + while (!stop[0]) { + synchronized (qt) { + try { + qt.wait(); + // if the following try/catch is moved outside the synchronized block, occasional NPEs result + try { + qt.put(p, p); + } catch (NullPointerException e) { + npe[0] = e; + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + } + }; + new Thread(r, "1").start(); + new Thread(r, "2").start(); + new Thread(r, "3").start(); + new Thread(r, "4").start(); + for (int i=0; i<10000000; i++) { + synchronized(qt) { + qt.notifyAll(); + } + assertNull("NullPointerException "+(npe[0]==null?"":npe[0].getMessage())+" during iteration "+i, npe[0]); + } + stop[0] = true; + } + @Test public void testDistance() { GLatLngQuadTree quadtree = new GLatLngQuadTree(new DegreePosition(49.29, diff --git a/java/com.sap.sailing.geocoding/src/com/sap/sailing/geocoding/impl/ReverseGeocoderImpl.java b/java/com.sap.sailing.geocoding/src/com/sap/sailing/geocoding/impl/ReverseGeocoderImpl.java index 4a6351fded5..5ae8488de53 100644 --- a/java/com.sap.sailing.geocoding/src/com/sap/sailing/geocoding/impl/ReverseGeocoderImpl.java +++ b/java/com.sap.sailing.geocoding/src/com/sap/sailing/geocoding/impl/ReverseGeocoderImpl.java @@ -194,7 +194,9 @@ public class ReverseGeocoderImpl implements ReverseGeocoder { private void cachePlacemarks(Position position, Double radius, List placemarks) { Collections.sort(placemarks, new Placemark.ByDistance(position)); if (position != null) { - cache.put(position, new Triple>(position, radius, placemarks)); + synchronized (cache) { + cache.put(position, new Triple>(position, radius, placemarks)); + } } } @@ -211,7 +213,9 @@ public class ReverseGeocoderImpl implements ReverseGeocoder { */ private void updateCachedPlacemarks(Position cachedPoint, Double newRadius, List newPlacemarks) { if (cachedPoint != null) { - cache.replace(cachedPoint, new Triple>(cachedPoint, newRadius, newPlacemarks)); + synchronized (cache) { + cache.replace(cachedPoint, new Triple>(cachedPoint, newRadius, newPlacemarks)); + } } } @@ -223,7 +227,9 @@ public class ReverseGeocoderImpl implements ReverseGeocoder { * {@link ReverseGeocoderImpl#POSITION_CACHE_DISTANCE_LIMIT the distance limit} */ private Triple> checkCache(Position position) { - return cache.get(position, POSITION_CACHE_DISTANCE_LIMIT); + synchronized (cache) { + return cache.get(position, POSITION_CACHE_DISTANCE_LIMIT); + } } private JSONArray callNearestService(Position position) throws MalformedURLException, IOException, ParseException { From d62a42079b3bb6900d50d0597c1a1bc3a6bf7e52 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Mon, 28 May 2012 21:17:32 +0200 Subject: [PATCH 28/32] synchronized all other access to QuadTree, too --- .../impl/DeclinationServiceImpl.java | 13 +++++++--- .../declination/impl/DeclinationStore.java | 24 +++++++++++++++---- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/java/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationServiceImpl.java b/java/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationServiceImpl.java index 31d584ae85b..f367854c858 100755 --- a/java/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationServiceImpl.java +++ b/java/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationServiceImpl.java @@ -57,7 +57,10 @@ public class DeclinationServiceImpl implements DeclinationService { int year = cal.get(Calendar.YEAR); QuadTree set; while ((set = getYearStore(year)) != null) { - Declination resultForYear = set.get(position); + Declination resultForYear; + synchronized (set) { + resultForYear = set.get(position); + } Distance spatialDistance = resultForYear.getPosition().getDistance(position); // consider result only if it's closer than maxDistance if (spatialDistance.compareTo(maxDistance) <= 0) { @@ -73,7 +76,9 @@ public class DeclinationServiceImpl implements DeclinationService { if (result == null) { QuadTree importerCacheForYear = importerCache.get(year); if (importerCacheForYear != null) { - result = importerCacheForYear.get(position); + synchronized (importerCacheForYear) { + result = importerCacheForYear.get(position); + } if (result.getPosition().getDistance(position).compareTo(maxDistance) <= 0) { return result; // else it's further away from the requested position as demanded by maxDistance @@ -85,7 +90,9 @@ public class DeclinationServiceImpl implements DeclinationService { importerCacheForYear = new QuadTree(); importerCache.put(year, importerCacheForYear); } - importerCacheForYear.put(result.getPosition(), result); + synchronized (importerCacheForYear) { + importerCacheForYear.put(result.getPosition(), result); + } } } return result; diff --git a/java/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationStore.java b/java/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationStore.java index cdf3330c584..c7765a741dc 100755 --- a/java/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationStore.java +++ b/java/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationStore.java @@ -49,7 +49,9 @@ public class DeclinationStore { result = new QuadTree(); BufferedReader in = new BufferedReader(new InputStreamReader(is)); while ((record = readExternal(in)) != null) { - result.put(record.getPosition(), record); + synchronized (result) { + result.put(record.getPosition(), record); + } } } return result; @@ -150,7 +152,10 @@ public class DeclinationStore { System.out.println("Date: " + year + "/" + (month + 1) + ", Latitude: " + lat); for (double lng = 0; lng < 180; lng += grid) { Position point = new DegreePosition(lat, lng); - Declination existingDeclinationRecord = storedDeclinations.get(point); + Declination existingDeclinationRecord; + synchronized (storedDeclinations) { + existingDeclinationRecord = storedDeclinations.get(point); + } if (existingDeclinationRecord == null || DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord .getPosition().getDistance(point), timePoint, existingDeclinationRecord @@ -161,7 +166,10 @@ public class DeclinationStore { } for (double lng = -grid; lng > -180; lng -= grid) { Position point = new DegreePosition(lat, lng); - Declination existingDeclinationRecord = storedDeclinations.get(point); + Declination existingDeclinationRecord; + synchronized (storedDeclinations) { + existingDeclinationRecord = storedDeclinations.get(point); + } if (existingDeclinationRecord == null || DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord .getPosition().getDistance(point), timePoint, existingDeclinationRecord @@ -175,7 +183,10 @@ public class DeclinationStore { System.out.println("Date: " + year + "/" + (month + 1) + ", Latitude: " + lat); for (double lng = 0; lng < 180; lng += grid) { Position point = new DegreePosition(lat, lng); - Declination existingDeclinationRecord = storedDeclinations.get(point); + Declination existingDeclinationRecord; + synchronized (storedDeclinations) { + existingDeclinationRecord = storedDeclinations.get(point); + } if (DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord.getPosition().getDistance(point), timePoint, existingDeclinationRecord.getTimePoint()) > 0.1) { // less than ~6 nautical miles and/or ~.6 months off @@ -184,7 +195,10 @@ public class DeclinationStore { } for (double lng = -grid; lng > -180; lng -= grid) { Position point = new DegreePosition(lat, lng); - Declination existingDeclinationRecord = storedDeclinations.get(point); + Declination existingDeclinationRecord; + synchronized (storedDeclinations) { + existingDeclinationRecord = storedDeclinations.get(point); + } if (DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord.getPosition().getDistance(point), timePoint, existingDeclinationRecord.getTimePoint()) > 0.1) { // less than ~6 nautical miles and/or ~.6 months off From 2709719005508f95463c86e17d1b7749acd97706 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Mon, 28 May 2012 21:21:57 +0200 Subject: [PATCH 29/32] re-enable additional data during creation of createStrippedLeaderboardDTO --- .../java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index bf5974ddef3..c1231aea193 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -1772,7 +1772,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS groupDTO.name = leaderboardGroup.getName(); groupDTO.description = leaderboardGroup.getDescription(); for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { - groupDTO.leaderboards.add(createStrippedLeaderboardDTO(leaderboard, false)); + groupDTO.leaderboards.add(createStrippedLeaderboardDTO(leaderboard, true)); } return groupDTO; } From 1a98a8cd6d80f917074475e4051010e141b44b4d Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Mon, 28 May 2012 22:21:46 +0200 Subject: [PATCH 30/32] enhanced comment regarding need for synchronization --- .../sailing/domain/common/quadtree/QuadTree.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/quadtree/QuadTree.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/quadtree/QuadTree.java index 477b1a2ba40..51f42e5f100 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/quadtree/QuadTree.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/quadtree/QuadTree.java @@ -32,11 +32,16 @@ import com.sap.sailing.domain.common.quadtree.impl.Bounds; import com.sap.sailing.domain.common.quadtree.impl.QuadTreeNode; /** - * The QuadTree lets you organize objects in a grid, that redefines - * itself and focuses more gridding when more objects appear in a - * certain area. + * The QuadTree lets you organize objects in a grid, that redefines itself and focuses more gridding when more objects + * appear in a certain area. + *

* - * @param type of object stored by coordinates + * Note that this class is not thread safe. If multiple threads can access the same instance concurrently, callers have + * to ensure proper synchronization. Concurrent reads are permissible while any write should block all other operations. + * + * @param + * type of object stored by coordinates + * @author Axel Uhl (D043530) */ public class QuadTree implements Serializable { From 15926116801ab82f79748673a475426053ba3433 Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Tue, 29 May 2012 10:04:29 +0200 Subject: [PATCH 31/32] Set Tool tips for "Home" and jump-to-leaderboard buttons see bug 672 --- .../gwt/ui/raceboard/GlobalNavigationPanel.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/GlobalNavigationPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/GlobalNavigationPanel.java index 608b8055f62..6c196e09185 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/GlobalNavigationPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/GlobalNavigationPanel.java @@ -36,9 +36,9 @@ public class GlobalNavigationPanel extends FlowPanel { if(showHomeNavigation) { if (leaderboardGroupName != null && !leaderboardGroupName.isEmpty()) { String leaderBoardGroupLink = spectatorViewLink + "?leaderboardGroupName=" + leaderboardGroupName; - addNavigationLink(leaderboardGroupName, leaderBoardGroupLink, "leaderBoardGroup"); + addNavigationLink(leaderboardGroupName, leaderBoardGroupLink, "leaderBoardGroup", "Go to the Event overview."); } else { - addNavigationLink(stringMessages.home(), homeLink, "home"); + addNavigationLink(stringMessages.home(), homeLink, "home", "Go to the Event overview."); } } @@ -47,11 +47,12 @@ public class GlobalNavigationPanel extends FlowPanel { if (leaderboardGroupName != null && !leaderboardGroupName.isEmpty()) { leaderBoardLink += "&leaderboardGroupName=" + leaderboardGroupName; } - addNavigationLink(leaderboardName, leaderBoardLink, "leaderBoard"); + addNavigationLink(leaderboardName, leaderBoardLink, "leaderBoard", "Go to the overview and see all Races in one Leaderboard"); } } - private void addNavigationLink(String linkName, String linkUrl, String styleNameExtension) { + private void addNavigationLink(String linkName, String linkUrl, String styleNameExtension, String htmlTitle) { + String setHtmlTitle = htmlTitle; String url = linkUrl; if(debugParam != null && !debugParam.isEmpty()) { url += url.contains("?") ? "&" : "?"; @@ -60,6 +61,7 @@ public class GlobalNavigationPanel extends FlowPanel { HTML linkHtml = new HTML(ANCHORTEMPLATE.anchor(URLFactory.INSTANCE.encode(url), linkName)); linkHtml.addStyleName(STYLE_NAME_PREFIX + styleNameExtension); + linkHtml.setTitle(setHtmlTitle); add(linkHtml); } } From 633a4b82d8dfecfe1288b4e1d93418b49fd1313c Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Tue, 29 May 2012 10:05:55 +0200 Subject: [PATCH 32/32] remove border from raceBoardNavigation-innerElement --- java/com.sap.sailing.gwt.ui/RaceBoard.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.gwt.ui/RaceBoard.css b/java/com.sap.sailing.gwt.ui/RaceBoard.css index 1c240905378..e5e7d71d2c9 100644 --- a/java/com.sap.sailing.gwt.ui/RaceBoard.css +++ b/java/com.sap.sailing.gwt.ui/RaceBoard.css @@ -230,7 +230,6 @@ input.opencoloumn { .raceBoardNavigation-innerElement { background: url("images/btn-cta-orangeleft.png") repeat-x scroll center 0 transparent; - border: medium none; border-bottom-left-radius: 3px; border-top-left-radius: 3px; color: #FFFFFF; @@ -239,6 +238,7 @@ input.opencoloumn { font-size: 14px; margin: 0 0 0 0; padding: 2px 7px 2px 3px; + height: 19px; } .raceBoardNavigation-innerElement:hover { background: url("images/btn-cta-orangeleft.png") repeat-x scroll center -30px transparent;