mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-07 21:01:03 +00:00
Solved master merge conflicts
This commit is contained in:
commit
17110b515e
298 files changed
+9342
-3327
No files matched your search
+315
-6
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file datatype="javapropertyresourcebundle" original="/usr/sap/ljs/app/Converter_4178050061048672287/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties" source-language="en">
|
||||
<file datatype="javapropertyresourcebundle" original="/usr/sap/ljs/app/Converter_7623614428299933729/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties" source-language="en">
|
||||
<header>
|
||||
<skl>
|
||||
<internal-file crc="f6ec166735cc7adb2ddad356f75a3f11" form="base64">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 truncated
|
||||
<internal-file crc="aa58aa0159559141c900793034ac8e1d" form="base64">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 truncated
|
||||
</skl>
|
||||
<phase-group>
|
||||
<phase company-name="SAP AG" date="2016-07-28T14:32:35Z" phase-name="file-creation" process-name="file-creation" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter"/>
|
||||
<phase company-name="SAP AG" date="2016-09-26T08:30:46Z" phase-name="file-creation" process-name="file-creation" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter"/>
|
||||
</phase-group>
|
||||
<tool tool-company="SAP AG" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter" tool-name="TEW: Javascript .properties Flexible File Converter" tool-version="1.1.0"/>
|
||||
</header>
|
||||
@@ -1490,6 +1490,24 @@
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="title" resname="title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="subtitle" resname="subtitle">
|
||||
<source>Subtitle</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="copyright" resname="copyright">
|
||||
<source>Copyright</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="widthInPx" resname="widthInPx">
|
||||
<source>Width (pixel)</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="heightInPx" resname="heightInPx">
|
||||
<source>Height (pixel)</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="tags" resname="tags">
|
||||
<source>Tags</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="size" resname="size">
|
||||
<source>Size</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="duration" resname="duration">
|
||||
<source>Duration (h:mm:ss.ms)</source>
|
||||
</trans-unit>
|
||||
@@ -3387,6 +3405,9 @@
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="useStartTimeInference" resname="useStartTimeInference">
|
||||
<source>Use start time inference from start mark passings</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="controlTrackingFromStartAndFinishTimes" resname="controlTrackingFromStartAndFinishTimes">
|
||||
<source>Control tracking from start and finish times</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="numberOfQueueMessagesSent" resname="numberOfQueueMessagesSent">
|
||||
<source>Number of queue messages sent</source>
|
||||
</trans-unit>
|
||||
@@ -4512,19 +4533,19 @@
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreCampaign" resname="playstoreCampaign">
|
||||
<source>utm_source=sapsailing&utm_medium=solutions&utm_content=2016.02&utm_campaign=solutions&pcampaignid=2016.sapsailing.solutions</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreTrackingApp" resname="playstoreTrackingApp">
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreInsightApp" resname="playstoreInsightApp">
|
||||
<source>https://play.google.com/store/apps/details?id=com.sap.sailing.android.tracking.app</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreRacecommitteeApp" resname="playstoreRacecommitteeApp">
|
||||
<source>https://play.google.com/store/apps/details?id=com.sap.sailing.racecommittee.app</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playStoreBuoypositioningApp" resname="playStoreBuoypositioningApp">
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playStoreBuoyPingerApp" resname="playStoreBuoyPingerApp">
|
||||
<source>https://play.google.com/store/apps/details?id=com.sap.sailing.android.buoy.positioning.app</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreBadge" resname="playstoreBadge">
|
||||
<source>https://play.google.com/intl/en/badges/images/generic/en-play-badge.png</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="appstoreSapSailingInsight" resname="appstoreSapSailingInsight">
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="appstoreSapSailInsight" resname="appstoreSapSailInsight">
|
||||
<source>http://appstore.com/sapsailinsight</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="appstoreStgTrainingstagebuch" resname="appstoreStgTrainingstagebuch">
|
||||
@@ -4824,6 +4845,294 @@
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="maximumNumberOfDiscards" resname="maximumNumberOfDiscards">
|
||||
<source>Maximum number of discards</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="notificationRegattaConfigurationUpdatedUsingByMarks" resname="notificationRegattaConfigurationUpdatedUsingByMarks">
|
||||
<source>Active regatta configuration was set, using the "By Marks" course designer.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="warningOverrideRegattaConfigurationCourseDesignerToByMarks" resname="warningOverrideRegattaConfigurationCourseDesignerToByMarks">
|
||||
<source>Active regatta configuration already exists, but with the wrong course designer setting.\nWould you like to override course designer setting to "By Marks"?</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="allRacesHaveBeenDenoted" resname="allRacesHaveBeenDenoted">
|
||||
<source>All races have been denoted for racelog tracking.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="chartSelectionHint" resname="chartSelectionHint">
|
||||
<source>Hint: You can also use the leaderboard (on the LEADERBOARD tab) to select the competitors displayed in the chart. </source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="chooseALanguage" resname="chooseALanguage">
|
||||
<source>Choose a language</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutions" resname="solutions">
|
||||
<source>Solutions</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="blog" resname="blog">
|
||||
<source>Blog</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="officalEventWebsite" resname="officalEventWebsite">
|
||||
<source>Official event website</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="moreInfo" resname="moreInfo">
|
||||
<source>More info</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="viewAnalysis" resname="viewAnalysis">
|
||||
<source>View analysis </source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="overallLeaderboard" resname="overallLeaderboard">
|
||||
<source>Overall leaderboard</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="pleaseTryAgain" resname="pleaseTryAgain">
|
||||
<source>Please try again...</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="reloadPage" resname="reloadPage">
|
||||
<source>Reload page</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="errorMessageLoadingData" resname="errorMessageLoadingData">
|
||||
<source>An error occured while loading the data for this page.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="regattaDetails" resname="regattaDetails">
|
||||
<source>Regatta details</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="chooseChartType" resname="chooseChartType">
|
||||
<source>Choose chart type</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="whatsNew" resname="whatsNew">
|
||||
<source>What''s new</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailing" resname="sapSailing">
|
||||
<source>SAP Sailing</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="search" resname="search">
|
||||
<source>Search</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownStartingInDays" resname="countdownStartingInDays">
|
||||
<source>Days</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownDays" resname="countdownDays">
|
||||
<source>Days</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownHours" resname="countdownHours">
|
||||
<source>Hrs</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownMinutes" resname="countdownMinutes">
|
||||
<source>Min</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownSeconds" resname="countdownSeconds">
|
||||
<source>Sec</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownDay" resname="countdownDay">
|
||||
<source>Day</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownHour" resname="countdownHour">
|
||||
<source>Hour</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownMinute" resname="countdownMinute">
|
||||
<source>Min</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownSecond" resname="countdownSecond">
|
||||
<source>Sec</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="liveCapitalLetter" resname="liveCapitalLetter">
|
||||
<source>Live</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="watchNow" resname="watchNow">
|
||||
<source>Watch now</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="seriesHeaderUpcoming" resname="seriesHeaderUpcoming">
|
||||
<source>Upcoming</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventRegattaLeaderboardLastScoreUpdate" resname="eventRegattaLeaderboardLastScoreUpdate">
|
||||
<source>Last Score Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventRegattaRaceNotTracked" resname="eventRegattaRaceNotTracked">
|
||||
<source>Not Tracked</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerJobs" resname="footerJobs">
|
||||
<source>Jobs</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerCopyright" resname="footerCopyright">
|
||||
<source>© 2011-2016 SAP Sailing Analytics</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerLanguage" resname="footerLanguage">
|
||||
<source>SAP Sailing in</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerLegal" resname="footerLegal">
|
||||
<source>Legal Disclosure</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerPrivacy" resname="footerPrivacy">
|
||||
<source>Privacy</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerFeedback" resname="footerFeedback">
|
||||
<source>Feedback</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="headerLogo" resname="headerLogo">
|
||||
<source>Sailing Analytics</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="headerSearchPlaceholder" resname="headerSearchPlaceholder">
|
||||
<source>Search </source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainEventShowAll" resname="mainEventShowAll">
|
||||
<source>Show All Events</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainEventTitle" resname="mainEventTitle">
|
||||
<source>Latest Events from the Sailing World</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaSubtitle" resname="mainMediaSubtitle">
|
||||
<source>Get lost in the latest and most beautiful impressions from your favorite sailing event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaTitle" resname="mainMediaTitle">
|
||||
<source>Photographers love Sailing</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaVideosSubtitle" resname="mainMediaVideosSubtitle">
|
||||
<source>Immerse yourself in the world of sailing and check out our latest events for more videos.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaVideosTitle" resname="mainMediaVideosTitle">
|
||||
<source>Recent Video Entries</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultHeaderButton" resname="searchResultHeaderButton">
|
||||
<source>Search</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultHeaderLabel" resname="searchResultHeaderLabel">
|
||||
<source>Your Search</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultHeaderPlaceholder" resname="searchResultHeaderPlaceholder">
|
||||
<source>Type in your searchkey</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultSortNewest" resname="searchResultSortNewest">
|
||||
<source>Recent</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsSISHeadline" resname="solutionsSISHeadline">
|
||||
<source>SAP in Sailing</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsSAPHeadline" resname="solutionsSAPHeadline">
|
||||
<source>SAP Sailing Analytics</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsRaceHeadline" resname="solutionsRaceHeadline">
|
||||
<source>SAP Sailing Race Manager</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsInSightHeadline" resname="solutionsInSightHeadline">
|
||||
<source>SAP Sail InSight</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsBuoyPingerHeadline" resname="solutionsBuoyPingerHeadline">
|
||||
<source>SAP Sailing Buoy Pinger</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsPostHeadline" resname="solutionsPostHeadline">
|
||||
<source>Post-Race Analytics</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsTrainingHeadline" resname="solutionsTrainingHeadline">
|
||||
<source>Training Diary</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsSimulatorHeadline" resname="solutionsSimulatorHeadline">
|
||||
<source>Strategy Simulator</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapInSailing" resname="sapInSailing">
|
||||
<source>SAP in Sailing</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing1" resname="contentSapInSailing1">
|
||||
<source>Sailing provides the perfect platform for SAP to showcase solutions and help the sport run like never before. SAP’s involvement in the sport has transformed the sailing experience by providing tools, which:</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing2" resname="contentSapInSailing2">
|
||||
<source>Help sailors analyze performance and optimize strategy</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing3" resname="contentSapInSailing3">
|
||||
<source>Bring fans closer to the action</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing4" resname="contentSapInSailing4">
|
||||
<source>Provide the media with information and insights to deliver a greater informed commentary</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing5" resname="contentSapInSailing5">
|
||||
<source>SAP has a longstanding involvement with sailing and has established a portfolio spanning across teams and regattas, including:</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing6" resname="contentSapInSailing6">
|
||||
<source>Official Technology Partner of Travemünder Woche</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing7" resname="contentSapInSailing7">
|
||||
<source>Technical Partner of the European Sailing Leagues</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing8" resname="contentSapInSailing8">
|
||||
<source>Title sponsor of the SAP Extreme Sailing Team</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing9" resname="contentSapInSailing9">
|
||||
<source>Official Technical Partner of the Extreme Sailing Series</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing10" resname="contentSapInSailing10">
|
||||
<source>Premium Partner of Germany’s national sailing team, Audi Sailing Team Germany</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing11" resname="contentSapInSailing11">
|
||||
<source>Premium Partner of the world’s largest regatta, Kieler Woche (Kiel Week)</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing12" resname="contentSapInSailing12">
|
||||
<source>Title sponsor of the SAP 5O5 World Championships</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingAnalyticsTitle" resname="sapSailingAnalyticsTitle">
|
||||
<source>SAP Sailing Analytics</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingAnalytics1" resname="contentSapSailingAnalytics1">
|
||||
<source>By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingAnalytics2" resname="contentSapSailingAnalytics2">
|
||||
<source>SAP Sailing Analytics provide insights and transparency to the world of sailing by utilizing Cloud and In-Memory Technology, processing GPS and wind measurement data in real time and visualizing contents in various frontends accessible from anywhere.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingAnalyticsReadMore" resname="sapSailingAnalyticsReadMore">
|
||||
<source>Read More</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingRaceManager" resname="sapSailingRaceManager">
|
||||
<source>SAP Sailing Race Manager</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingRaceManager" resname="contentSapSailingRaceManager">
|
||||
<source>The SAP Sailing Race Manager delivers greater efficiency and control to race organizers by automating and simplifying their manual tasks and communication during running sailing regattas. The Race Committee App helps simplify the operation of running and managing race events to help race committees operate smarter.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingRaceManagerReadMore" resname="sapSailingRaceManagerReadMore">
|
||||
<source>Learn More</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailInSight" resname="sapSailInSight">
|
||||
<source>SAP Sail InSight</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailInSight" resname="contentSapSailInSight">
|
||||
<source>With the SAP Sail InSight mobile app for iPhone, iPad and Android phones, sailboat racers can manage their regatta participation and performance anywhere and anytime. This app connects to the SAP Sailing Analytics solution and enables racers to sign in to an SAP Sail InSight-enabled regatta, track their location together with performance indicators like speed or distance sailed, and analyze their performance.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailInSightReadMore" resname="sapSailInSightReadMore">
|
||||
<source>Learn More</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingBuoyPinger" resname="sapSailingBuoyPinger">
|
||||
<source>SAP Sailing Buoy Pinger</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingBuoyPinger" resname="contentSapSailingBuoyPinger">
|
||||
<source>With the SAP Sailing Buoy Pinger mobile app for Android phones, sailboat race managers can simplify the positioning of race marks and communication with the mark layers anywhere and anytime. This app connects to the SAP Sailing Analytics solution and allows regatta managers to track the geographical position of their race marks, enabling the use of the SAP Sail InSight mobile app by sailors participating in the regatta.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingBuoyPingerReadMore" resname="sapSailingBuoyPingerReadMore">
|
||||
<source>Learn More</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="postRaceAnalytics" resname="postRaceAnalytics">
|
||||
<source>Post-Race Analytics</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentPostRaceAnalytics1" resname="contentPostRaceAnalytics1">
|
||||
<source>Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentPostRaceAnalytics2" resname="contentPostRaceAnalytics2">
|
||||
<source>SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="i18nDeSolutionsTrainingHeadline" resname="i18nDeSolutionsTrainingHeadline">
|
||||
<source>SAP Sail Better – STG Training Diary</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="i18nDeSolutionsTrainingText" resname="i18nDeSolutionsTrainingText">
|
||||
<source>The STG Training Diary supports the daily documentation and analysis of an athlete’s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="strategySimulator" resname="strategySimulator">
|
||||
<source>Strategy Simulator</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentStrategySimulator" resname="contentStrategySimulator">
|
||||
<source>Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions.</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="strategySimulatorReadMore" resname="strategySimulatorReadMore">
|
||||
<source>Learn More</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="impressum" resname="impressum">
|
||||
<source>Imprint</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="lastFix" resname="lastFix">
|
||||
<source>Last fix</source>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="filterDeviceMappings" resname="filterDeviceMappings">
|
||||
<source>Filter device mappings</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
+447
-62
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-08-12T10:45:38Z" original="/usr/sap/ljs/app/Converter_4178050061048672287/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties" source-language="en" target-language="ja">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-09-29T12:17:16Z" original="/usr/sap/ljs/app/Converter_7623614428299933729/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties" source-language="en" target-language="ja">
|
||||
<header>
|
||||
<skl>
|
||||
<internal-file crc="f6ec166735cc7adb2ddad356f75a3f11" form="base64">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 truncated
|
||||
<internal-file crc="aa58aa0159559141c900793034ac8e1d" form="base64">H4sIAAAAAAAAAMy9a3PcSJIl+h2/AtNtdyXZkqlHTffsqA1WN0VKKs6IjyapUveuro2BmSCJUSaQA2SKYrXVf79+jrtHBPJBqnr7rt2yUhKIFwKBCA8Pfxyfl015U726KOtZcRyvs66cVAftfF4vl1U1XiyKc0nItUSXSwJL/FxXd1WneV95nc3LxUHbLLt21kuDi3xiN9lCahZn8pMtpeql/Hv7tWqWfXFpt7neZ/1d3feX9bxubqzERUzxQmjjSzV9U123XVX8VPfLtrvP2+vcMvJKy91UTdWVs+K9/s1mUhLd7YsPcpXzUhOrm3K5LD3d7rK7upkWn+RHXqypVl+r7vJ+UWGoeMP8M7mZfSivqllxeVv3ufy/vK1y1MqZl9/d1pPbvG/z67JD9qSdL2bVsprd59V8sbwfZV113VX9bXGuf+V+3n6t5BZ/+JSLdtVNKvYl1+tsWs4XVSOjctQsq+6rvOahp+SehA+CD8HvxS/Fq77QV7fhKuyvDEUjf3yEcG1jtKznVSHfoOLVZdvOlvWCCXxZvFG1rOUr5L3MH6nWNpIh7zqrbkb5O0lHseu6k9GVJM3jUKykp9P8umvnMk5Vs97coux7yUdqvyw7qV031ShbzMr7i0UlXT+Tq7zHZUz8qZotio99lf/u5e9ymSJ5V92sZjL4KLF/Je+qNfby373SAtN2dTWr9pnKUixUymDLZ2sbNn3cTqsPtXwW/ISU8wpXhf7JkcIhOqyQyt94z359qMqvlX74fNlK11ixXOZld1XLh5CJjAr9n/IKHzHvK1lE0z5/Wo1uRtLjP77QLrdNlcuaWC2rXO5+Z6mNJD/DSpjigfkVV4gMmjxyWi7L/BoDxdc8av69abG8+M5PvzTPMnyFw+qmeIev8XRa3TzLmpYT4K/VUmZ3JU2V8q+RbiM1v6+Wo2zZLmXufV69+GH8QzYpu+6+GE8mq7mMuHzaLH7M4iBcJql9ktyn6RfVrJpIC8XfXvz6/G8vf02mRS+jopkj6eHFanIrozqtuqu27KbFSZv3kiQTLaRlybUQqOv6ZtWVy7ptiqRiPsjJmurusF3q/8VJdTcajbJqWi8vJjKkffFWLvOzthY6g5xJO1vNm5NSvtxR411Pe0Uyyfy8bnIvkSdFsnI6jU8cT6dot6saqROTz3mPHFu056TVTcPmLltvGMl4GgmsL+Q8FMTUC30IXSMBuGwP+C6kACint9mqQW7xkX/SAeVj0nFkU5OymQhNPOAfWS5V2VdvMaPHLH/GBJvjZY6XGhR605bLg5ms/vWS8ohlPkFONq17mW9KrzBnf2rvhDTfX4BQGBk7bYpDLaULBqsBc1epCUjlXb28zW/bu1xI/L0my5B0ujXEl/okxUDf0fnxrJOM+7ffZLPoB2/Oxkjc8EJ5qQXziiW9v5e3IPLtbNofr/rlm+pkNa+6ehI6ugz5+VwKyCLOGy2yq4VxP6maqbzNQ22UXshbScoj1UcEIylduqq602vdCi58rEimw1jpGOkEHcx0pqzPbJ1Fl21aUua4zS7Ms7RCMhUw4rKDyArUqc65uWX6KP2r7vT76nrM2i/F6b9n82pazlC7OMZVrhshu8lU6zGTW9lCt63fU0nfvmy7UpbFufzwyjfHSNWePOlz5GDdYyPr9OnkMc5ZV69zbSNmfEdTWjgTNkH4mxlbO9VrbS3JeLy1XuYYNnsQ9PNd/ZOBnZWLvir2s+rbQrbI4r/LOrkpPmBaLbHaj5pj4W6EsB9aQlaiFzfVRbrvfF69evXiDznTthUITIZ0zLJ1187xTvlNJ6zDNJ+uOkxM5zX2PjeTcjbRrcdXo2x99de6F5pOFpH32jHwi18r8CtX98zAzitzqJpiZ8F3Gv8jOoaG/sE9a768L+uGsy7HVUhKezetr69lz0Zz1vyi7WtsbrqSyWutOimxJK/DEl31tW5XyrllfbnAgUDeZNyUs/tlPRFqoAl5SEnJZEoN0/QBmRzUuKiWoC1DOuqJWe+5SQqW4HgpxfvlaSOU5+awWuIEo4sTrBSIw5IEH8zmlNmZvSk/JdbIe36owAadvn+4RDqwPmgbn104hF6+FL7xJRnlk+rb8lN5vwCfAL6AvFzx9nL8XQXTZ4byOhWWt/Kea8wypkevTGU50fnVSLP5nbW7l1+VvTPnaU0QAn8nmXXtpBbmdC6fI79pW2GTpTN9LR9HZzQm56rKcSyRKdbJmMuMGmU35cKpe3zT93IIlA7p995axN/xrb2fHp+exsXyTHjOrpbDjL64v7Z1N8xom+FkDzg4svDkwCVpMhXKW3moLMHw/r5wfz5+z30jbRJzBsuBi3RRdZI/55qs/muFXrTavj2Qu42+H1vqV1e9FLSG+tHnBl/vBuNQzWa9bp9gT6uym9VVt/4R79rVbJrf4pBwW5JPk737jrx3HzspZ8e6/yxnPWH+8WR8dNCCpIvDrtmwLbr2P3UH80H9nvEcjuMo8zlyLE2/lxnii0hGc1deOpW3TTE9JNvhGVPrTujA81lV4a8tNAzvaoHM59P2ruEExBjvyYSXEjIPpeX7vdy+Zzlrm5t9sslJA1wbmMj8Opk/yveqy/Z9GzawT5aZkOVW+vtgJX/RT+vvENqItHfrAgxfwL6iMG3+MTAz/zcGIfbge8Yh8gnv7POP8fXD4MjS/u21Hh8de9VkRdg4JCnD+ZjyVf8fDc/n5qRdbie622kNUmTaC/0VHrkvu1oWLFaiU1D2tb6WJS4s+USIA1YvMmseDxczyZezLU5KejCD1OAthAbCCh9W1+VqthyIEijF0HQ9GQq/TGmZHgBzuVWpmOaWV7NKmftLv3VRD+7xeawixV/GZ/Lk5twgj2xsksl8WJKoCXqqwBanpwjScE08veYDcArRLJff4TAikz7Jf2tLwHOtO94Vv++LILnTxw7bD9X7ZbtI8tpFzJroAVmWH+QS4Tq7VRnj6XWSmAoek3qZfIa6qWTAY9nikGk4qch3iIXTQ3wfjup6sJID9IUMwzk2E5wz5SQtHLqMRGcp3tkxCpXWhj2TGxgOn9bYou2kiTP8ZpAGHZYyfB9cLIQR6aopEy94qcnCw/bFx/OjPvvPvm0+drPi3y5OT/KP5x/YCJpjmzlbOowtxRxrjnmo87Gr9bnSrBVGkhVDospuE5GGzqQ+Pwhbnw1Udtv2S66Rn+xCxn4izCkFOAe31eTLVftNhqQDk6Ii2Tey7WKdCVt9GMuS179I54ydM/02N6FCtihXfTVeLVvhVeqJCWyLM6TmpSfnJtDNkHI+FO7GUnIuu88op4v8EuWE+dP+mWa8qZZ3VdXgeePpVxAnL3KlOWxtf7WYknOqGxcXvtb6JmBomxMsDAgveS5gCy4XuJFpsiQfIhPsl6prs8lt2/bVRzbqkuTT68hya2eLAxbL9eHybC2I1TBgwbVHWdV1bWdcPL6E0DGevd8iPTc+X5lK0l8cklnnXbUkJUalo4bMGD7ZsP61FdIG6lhsrbFPt/WsuuzupShkZctPQbY+bO8O5YQs3JNgt+hf/ju2TcrS2x7zu/x6Vt5kdaOkVsbfaGxbLFv5vRCuGVe9cH3O4E5JXC/AB0aeHo1BUAyKpLoOTkk92ciuieIqQrQkP9kPS/jZ3wvN/HDkBeS0FDJVRHIsDX1cFB8Xyf2h7JwFfkg3uJCTFSIU3FYHO+QrA+942szuXUaSiHX1bVvJDILbVJrLqluq4WtrVXxQYUW/KYe9rQm80oequVneFpdyKfMP11xJfSISFZ6OjKbKr5XXvm9X+az+QuZOeADI43/MtH5cmB+S9payjvtL+XhCtnCZ4zprTGbm2qE+6In6zbyUHdZMZ3xc09S7KqVOVCmbDR01eK3tze1sqiN3sRTSJpsOfrP/rK9kbP4Nv9mikpP98v6g7iYzSTzT29zuozDtqD9ZzWYqUiM/I6t/VZHtkTnY3lH4n8rah/L1VKWWjpVSn4NbmVVOYia4CfKlSxONBPlS7ikbRYbSkHXRSmDEwVereiny3J+bhPU01pwHUDtK15Elr/vmyRM5JdVNLUc0kxwd/n1dicLp394XZSrXO7N+IPsgHG/xsx/BkJojWbVCUezBYqocQmKuqekRniVwwL902W3G/sjk/tCW00KVIzz+y622ry2G7xRFhHUj1DOz3etjUy+L3u/OIANeccM8lmmsmc9PjmUm4kjB+7nsd7KRVXr3efXixdWLbDKTyVMc4JeKpbKrDtb0TlBnpWRkWvWTrl4YzxauMywgFYpT/mWLLKP+sruXpvg3a9ofPshOVnUHrbRUfGzIWMsIXNcmXzs6Pch/2J+x0P4EpUaQjkMUji1b3ggbvPwhUeQqMPLJRdBzbu1WRox1Eph8sVxu00OMHm5DKIqx19/TWKQpWmmU4fgjG8pPYD5Xi+xKGK7xXXlfgPPKyzsoRIXkkO7waiBPnWMgSQpBlrbTLdAqkipeba9Oera9+oC8Beo24e0wc3vTi0GNHQ+Zl92Xs7LvsZ8fyzUV2djVkcGUrJXp0DnZk6nypZENN9DsbNqubmalTP6VsLqdriXZk5kofWCqrv8+u65nMp24v72552nsHVNsmxNel8yxFhN6XZfDYnMkhWI8kwSxrJ4CXQ6blTy3QPlJDWhyny4tKkfTdRWLperTnteWCQXLm66962U0qGyREbV7K3E+MItImqTeQpvUa68grx+6mvNUzylMfjAW+ZhqNtczBw9NM99+A3P0l+MPhV7l8l3kLnmbw7K/TZRHBy2ksiHRPkcqFx9+lVR8Hj5OaWfPsR02616NNoqjPter7F7G4q8yBk1bnLRyRpLZBAo+5hySoxKoOX9KnT8mO1CmsDENMgggFOl+Q5px1P87JqnwktigPpIFVibQuGKSCmWNsTPaWa5w2x6bRMJqY7LI4UD64xONvfjbi1+lB1rLine truncated
|
||||
</skl>
|
||||
<phase-group>
|
||||
<phase company-name="SAP AG" date="2016-07-28T14:32:35Z" phase-name="file-creation" process-name="file-creation" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter"/>
|
||||
<phase company-name="SAP AG" date="2016-09-26T08:30:46Z" phase-name="file-creation" process-name="file-creation" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter"/>
|
||||
</phase-group>
|
||||
<tool tool-company="SAP AG" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter" tool-name="TEW: Javascript .properties Flexible File Converter" tool-version="1.1.0"/>
|
||||
</header>
|
||||
@@ -165,8 +165,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="competitorsSelected" resname="competitorsSelected">
|
||||
<source><ph id="1">{0}</ph>/<ph id="2">{1}</ph> competitors selected.</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>/<ph id="2">{1}</ph> の競技者が選択されました。</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>/<ph id="2">{1}</ph> の競技者が選択されました。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="noSuchLeaderboard" resname="noSuchLeaderboard">
|
||||
<source>No such leaderboard</source>
|
||||
@@ -938,8 +937,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="settingsForComponent" resname="settingsForComponent">
|
||||
<source>Settings for <ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> の設定</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> の設定</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="noEventsFound" resname="noEventsFound">
|
||||
<source>No events were found</source>
|
||||
@@ -1003,13 +1001,11 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="competitorPassedMarkAtDate" resname="competitorPassedMarkAtDate">
|
||||
<source><ph id="1">{0}</ph> passed <ph id="2">{1}</ph> at <ph id="3">{2}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> が <ph id="3">{2}</ph> に <ph id="2">{1}</ph> を通過</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> が <ph id="3">{2}</ph> に <ph id="2">{1}</ph> を通過</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="valueForCompetitorAt" resname="valueForCompetitorAt">
|
||||
<source><ph id="1">{0}</ph> at <ph id="2">{1}</ph>: <ph id="3">{2}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="2">{1}</ph> での <ph id="1">{0}</ph>: <ph id="3">{2}</ph></target>
|
||||
<target state="signed-off"><ph id="2">{1}</ph> での <ph id="1">{0}</ph>: <ph id="3">{2}</ph></target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="reallyRemoveRace" resname="reallyRemoveRace">
|
||||
<source>Do you really want to remove the race ''<ph id="1">{0}</ph>''? Note: all race logs for this race will also permanently be removed!</source>
|
||||
@@ -1105,8 +1101,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="noLeaderboardGroupWithNameFound" resname="noLeaderboardGroupWithNameFound">
|
||||
<source>No leaderboard group with the name <ph id="1">{0}</ph> found</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> という名称のリーダーボードグループは見つかりませんでした</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> という名称のリーダーボードグループは見つかりませんでした</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="overview" resname="overview">
|
||||
<source>Overview</source>
|
||||
@@ -1988,6 +1983,30 @@
|
||||
<source>Title</source>
|
||||
<target state="signed-off">表題</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="subtitle" resname="subtitle">
|
||||
<source>Subtitle</source>
|
||||
<target state="signed-off">サブタイトル</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="copyright" resname="copyright">
|
||||
<source>Copyright</source>
|
||||
<target state="signed-off">著作権</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="widthInPx" resname="widthInPx">
|
||||
<source>Width (pixel)</source>
|
||||
<target state="signed-off">幅 (ピクセル)</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="heightInPx" resname="heightInPx">
|
||||
<source>Height (pixel)</source>
|
||||
<target state="signed-off">高さ (ピクセル)</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="tags" resname="tags">
|
||||
<source>Tags</source>
|
||||
<target state="signed-off">タグ</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="size" resname="size">
|
||||
<source>Size</source>
|
||||
<target state="signed-off">サイズ</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="duration" resname="duration">
|
||||
<source>Duration (h:mm:ss.ms)</source>
|
||||
<target state="signed-off">時間 (h:mm:ss.ms)</target>
|
||||
@@ -2190,8 +2209,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="passedTo" resname="passedTo">
|
||||
<source>passed to <ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> に受け渡し済</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> に受け渡し済</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="gapChangeSinceLegStartInSeconds" resname="gapChangeSinceLegStartInSeconds">
|
||||
<source>Gap Change</source>
|
||||
@@ -3511,8 +3529,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="queryResultsChartSubtitle" resname="queryResultsChartSubtitle">
|
||||
<source>Worked through <ph id="1">{0}</ph> data entries in <ph id="2">{1}</ph> seconds</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> データエントリを <ph id="2">{1}</ph> 秒で処理済</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> データエントリを <ph id="2">{1}</ph> 秒で処理済</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="noQuerySelected" resname="noQuerySelected">
|
||||
<source>No query selected</source>
|
||||
@@ -3544,8 +3561,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="windImport_ResultHeader" resname="windImport_ResultHeader">
|
||||
<source>Imported wind from: <ph id="1">{0}</ph> to: <ph id="2">{1}</ph>. <ph id="3">{2}</ph> races affected.</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> から <ph id="2">{1}</ph> に風をインポートしました。<ph id="3">{2}</ph> レースが影響を受けます。</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> から <ph id="2">{1}</ph> に風をインポートしました。<ph id="3">{2}</ph> レースが影響を受けます。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="windImport_ResultEntry" resname="windImport_ResultEntry">
|
||||
<source>Race: <ph id="1">{0}</ph> (<ph id="2">{1}</ph>) - <ph id="3">{2}</ph> fixes from: <ph id="4">{3}</ph> to: <ph id="5">{4}</ph></source>
|
||||
@@ -3829,8 +3845,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="classFlagHelpText" resname="classFlagHelpText">
|
||||
<source>Sets the class flag used for <ph id="1">{0}</ph>. Choose ''Don''t Overwrite'' to activate the procedure''s default flag.</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> に使用するクラス旗を選定します。手順にある初期値の旗を有効化するには、''上書きしない'' を選択してください。</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> に使用するクラス旗を選定します。手順にある初期値の旗を有効化するには、''上書きしない'' を選択してください。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="individualRecallHelpText" resname="individualRecallHelpText">
|
||||
<source>When activated the Race Officer is able to call for individual recall.</source>
|
||||
@@ -4118,23 +4133,19 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="edit_what" resname="edit_what">
|
||||
<source>Edit <ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> を編集</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> を編集</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="add_what" resname="add_what">
|
||||
<source>Add <ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> を追加</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> を追加</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="remove_what" resname="remove_what">
|
||||
<source>Remove <ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> を削除</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> を削除</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="pleaseEnterA" resname="pleaseEnterA">
|
||||
<source>Please enter a <ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> を入力してください</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> を入力してください</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="pingPosition" resname="pingPosition">
|
||||
<source>Ping <ph id="1">{0}</ph> position</source>
|
||||
@@ -4142,8 +4153,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="pleaseEnterAValidValueFor" resname="pleaseEnterAValidValueFor">
|
||||
<source>Please enter a valid value for <ph id="1">{0}</ph> (<ph id="2">{1}</ph>)</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> の有効な値を入力してください (<ph id="2">{1}</ph>)</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> の有効な値を入力してください (<ph id="2">{1}</ph>)</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="copyCourseAndCompetitors" resname="copyCourseAndCompetitors">
|
||||
<source>Copy course and competitors to other races</source>
|
||||
@@ -4351,14 +4361,12 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventSharingShortText" resname="eventSharingShortText">
|
||||
<source><ph id="1">{0}</ph> in <ph id="2">{1}</ph> on <ph id="3">{2}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="2">{1}</ph> の <ph id="1">{0}</ph> を <ph id="3">{2}</ph> で</target>
|
||||
<target state="signed-off"><ph id="2">{1}</ph> の <ph id="1">{0}</ph> を <ph id="3">{2}</ph> で</target>
|
||||
<note annotates="source" from="Developer">String eventSharingShortText(String eventName, String venue, String dateString);</note>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventSharingLongText" resname="eventSharingLongText">
|
||||
<source>I''d like to share <ph id="1">{0}</ph> in <ph id="2">{1}</ph> on <ph id="3">{2}</ph>. Details on: \n<ph id="4">{3}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="2">{1}</ph> の <ph id="1">{0}</ph> を <ph id="3">{2}</ph> でシェアします。詳細: \n<ph id="4">{3}</ph></target>
|
||||
<target state="signed-off"><ph id="2">{1}</ph> の <ph id="1">{0}</ph> を <ph id="3">{2}</ph> でシェアします。詳細: \n<ph id="4">{3}</ph></target>
|
||||
<note annotates="source" from="Developer">String eventSharingLongText(String eventName, String venue, String dateString, String url);</note>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="seriesSharingLongText" resname="seriesSharingLongText">
|
||||
@@ -4368,9 +4376,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="seriesSharingShortText" resname="seriesSharingShortText">
|
||||
<source><ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>
|
||||
</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph></target>
|
||||
<note annotates="source" from="Developer">String seriesSharingShortText(String seriesName);</note>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="competitorsAnalytics" resname="competitorsAnalytics">
|
||||
@@ -4529,6 +4535,10 @@
|
||||
<source>Use start time inference from start mark passings</source>
|
||||
<target state="signed-off">スタートマーク通過からの推定スタート時刻を使用</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="controlTrackingFromStartAndFinishTimes" resname="controlTrackingFromStartAndFinishTimes">
|
||||
<source>Control tracking from start and finish times</source>
|
||||
<target>スタート時刻およびフィニッシュ時刻からの追跡の制御</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="numberOfQueueMessagesSent" resname="numberOfQueueMessagesSent">
|
||||
<source>Number of queue messages sent</source>
|
||||
<target state="signed-off">送信済キューメッセージ数</target>
|
||||
@@ -4623,8 +4633,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mediaSelectVideoCaption" resname="mediaSelectVideoCaption">
|
||||
<source><ph id="1">{0}</ph> Videos</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> 動画</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> 動画</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mediaSelectVideoTooltip" resname="mediaSelectVideoTooltip">
|
||||
<source>Click to select video</source>
|
||||
@@ -5296,8 +5305,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="startingIn" resname="startingIn">
|
||||
<source><ph id="1">{0}</ph> starts in</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> がスタート:</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> がスタート:</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="raceIsPlanned" resname="raceIsPlanned">
|
||||
<source>Planned</source>
|
||||
@@ -5329,8 +5337,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="competitorWonRace" resname="competitorWonRace">
|
||||
<source><ph id="1">{0}</ph> won race</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> がレースに勝利</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> がレースに勝利</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="showCompetitorTimeOnTimeFactorColumn" resname="showCompetitorTimeOnTimeFactorColumn">
|
||||
<source>Time on Time Factor</source>
|
||||
@@ -5454,8 +5461,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="collapseX" resname="collapseX">
|
||||
<source>Collapse <ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> を圧縮</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> を圧縮</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="numberOfGPSFixes" resname="numberOfGPSFixes">
|
||||
<source>GPS fixes</source>
|
||||
@@ -5503,13 +5509,11 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="minutesAgo" resname="minutesAgo">
|
||||
<source><ph id="1">{0}</ph> min ago</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> 分前</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> 分前</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="hoursAgo" resname="hoursAgo">
|
||||
<source><ph id="1">{0}</ph> h ago</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> 時間前</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> 時間前</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="winner" resname="winner">
|
||||
<source>Winner</source>
|
||||
@@ -5597,8 +5601,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="cantDisplayDataOfType" resname="cantDisplayDataOfType">
|
||||
<source>Can''t display data of type <ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> タイプのデータは表示できません。</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> タイプのデータは表示できません。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="shownDecimals" resname="shownDecimals">
|
||||
<source>Shown Decimals</source>
|
||||
@@ -5634,8 +5637,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventsHaveTakenPlace" resname="eventsHaveTakenPlace">
|
||||
<source><ph id="1">{0}</ph> events have taken place</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> イベントが行われました</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> イベントが行われました</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventsHaveTakenPlace[one]" resname="eventsHaveTakenPlace[one]">
|
||||
<source>One event has taken place</source>
|
||||
@@ -5815,8 +5817,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="imageSizeError" resname="imageSizeError">
|
||||
<source>The size of the <ph id="1">{0}</ph> image does not fit. The width should be between <ph id="2">{1}</ph> and <ph id="3">{2}</ph> px and the height between <ph id="4">{3}</ph> and <ph id="5">{4}</ph> px.</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> 画像のサイズが適合しません。幅は <ph id="2">{1}</ph> と <ph id="3">{2}</ph> px の間、高さは <ph id="4">{3}</ph> と <ph id="5">{4}</ph> px の間である必要があります。</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> 画像のサイズが適合しません。幅は <ph id="2">{1}</ph> と <ph id="3">{2}</ph> px の間、高さは <ph id="4">{3}</ph> と <ph id="5">{4}</ph> px の間である必要があります。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="couldNotRetrieveImageSizeYet" resname="couldNotRetrieveImageSizeYet">
|
||||
<source>The width and height of the image could not be retrieved yet.</source>
|
||||
@@ -6038,25 +6039,25 @@
|
||||
<source>utm_source=sapsailing&utm_medium=solutions&utm_content=2016.02&utm_campaign=solutions&pcampaignid=2016.sapsailing.solutions</source>
|
||||
<target state="signed-off">utm_source=sapsailing&utm_medium=solutions&utm_content=2016.02&utm_campaign=solutions&pcampaignid=2016.sapsailing.solutions</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreTrackingApp" resname="playstoreTrackingApp">
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreInsightApp" resname="playstoreInsightApp">
|
||||
<source>https://play.google.com/store/apps/details?id=com.sap.sailing.android.tracking.app</source>
|
||||
<target state="signed-off">https://play.google.com/store/apps/details?id=com.sap.sailing.android.tracking.app</target>
|
||||
<target>https://play.google.com/store/apps/details?id=com.sap.sailing.android.tracking.app</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreRacecommitteeApp" resname="playstoreRacecommitteeApp">
|
||||
<source>https://play.google.com/store/apps/details?id=com.sap.sailing.racecommittee.app</source>
|
||||
<target state="signed-off">https://play.google.com/store/apps/details?id=com.sap.sailing.racecommittee.app</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playStoreBuoypositioningApp" resname="playStoreBuoypositioningApp">
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playStoreBuoyPingerApp" resname="playStoreBuoyPingerApp">
|
||||
<source>https://play.google.com/store/apps/details?id=com.sap.sailing.android.buoy.positioning.app</source>
|
||||
<target state="signed-off">https://play.google.com/store/apps/details?id=com.sap.sailing.android.buoy.positioning.app</target>
|
||||
<target>https://play.google.com/store/apps/details?id=com.sap.sailing.android.buoy.positioning.app</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreBadge" resname="playstoreBadge">
|
||||
<source>https://play.google.com/intl/en/badges/images/generic/en-play-badge.png</source>
|
||||
<target state="signed-off">https://play.google.com/intl/en/badges/images/generic/en-play-badge.png</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="appstoreSapSailingInsight" resname="appstoreSapSailingInsight">
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="appstoreSapSailInsight" resname="appstoreSapSailInsight">
|
||||
<source>http://appstore.com/sapsailinsight</source>
|
||||
<target state="signed-off">http://appstore.com/sapsailinsight</target>
|
||||
<target>http://appstore.com/sapsailinsight</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="appstoreStgTrainingstagebuch" resname="appstoreStgTrainingstagebuch">
|
||||
<source>http://appstore.com/stgtrainingstagebuch</source>
|
||||
@@ -6454,6 +6455,390 @@
|
||||
<source>Maximum number of discards</source>
|
||||
<target state="signed-off">カットレースの最大数</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="notificationRegattaConfigurationUpdatedUsingByMarks" resname="notificationRegattaConfigurationUpdatedUsingByMarks">
|
||||
<source>Active regatta configuration was set, using the "By Marks" course designer.</source>
|
||||
<target state="signed-off">"マーク別" コースデザイナーを使用して、有効なレガッタ設定が行われました。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="warningOverrideRegattaConfigurationCourseDesignerToByMarks" resname="warningOverrideRegattaConfigurationCourseDesignerToByMarks">
|
||||
<source>Active regatta configuration already exists, but with the wrong course designer setting.\nWould you like to override course designer setting to "By Marks"?</source>
|
||||
<target state="signed-off">有効なレガッタ設定がすでに登録されていますが、コースデザイナーの設定が適切でありません。\n"マーク別" へのコースデザイナー設定を上書きしますか。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="allRacesHaveBeenDenoted" resname="allRacesHaveBeenDenoted">
|
||||
<source>All races have been denoted for racelog tracking.</source>
|
||||
<target state="signed-off">すべてのレースがレースログ追跡に表示されています。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="chartSelectionHint" resname="chartSelectionHint">
|
||||
<source>Hint: You can also use the leaderboard (on the LEADERBOARD tab) to select the competitors displayed in the chart. </source>
|
||||
<target>ヒント: リーダーボード (リーダーボードタブ内) を使用して、チャートに表示する競技者を選択することもできます。 </target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="chooseALanguage" resname="chooseALanguage">
|
||||
<source>Choose a language</source>
|
||||
<target>言語を選択してください</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutions" resname="solutions">
|
||||
<source>Solutions</source>
|
||||
<target>ソリューション</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="blog" resname="blog">
|
||||
<source>Blog</source>
|
||||
<target>ブログ</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="officalEventWebsite" resname="officalEventWebsite">
|
||||
<source>Official event website</source>
|
||||
<target>公式イベント Web サイト</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="moreInfo" resname="moreInfo">
|
||||
<source>More info</source>
|
||||
<target>追加情報</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="viewAnalysis" resname="viewAnalysis">
|
||||
<source>View analysis </source>
|
||||
<target>分析の表示 </target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="overallLeaderboard" resname="overallLeaderboard">
|
||||
<source>Overall leaderboard</source>
|
||||
<target>全体リーダーボード</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="pleaseTryAgain" resname="pleaseTryAgain">
|
||||
<source>Please try again...</source>
|
||||
<target>再試行してください...</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="reloadPage" resname="reloadPage">
|
||||
<source>Reload page</source>
|
||||
<target>ページのリロード</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="errorMessageLoadingData" resname="errorMessageLoadingData">
|
||||
<source>An error occured while loading the data for this page.</source>
|
||||
<target>このページのデータのロードでエラーが発生しました。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="regattaDetails" resname="regattaDetails">
|
||||
<source>Regatta details</source>
|
||||
<target>レガッタ詳細</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="chooseChartType" resname="chooseChartType">
|
||||
<source>Choose chart type</source>
|
||||
<target>チャートタイプ選択</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="whatsNew" resname="whatsNew">
|
||||
<source>What''s new</source>
|
||||
<target>最新情報</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailing" resname="sapSailing">
|
||||
<source>SAP Sailing</source>
|
||||
<target>SAP Sailing</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="search" resname="search">
|
||||
<source>Search</source>
|
||||
<target>検索</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownStartingInDays" resname="countdownStartingInDays">
|
||||
<source>Days</source>
|
||||
<target>日</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownDays" resname="countdownDays">
|
||||
<source>Days</source>
|
||||
<target>日</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownHours" resname="countdownHours">
|
||||
<source>Hrs</source>
|
||||
<target>時間</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownMinutes" resname="countdownMinutes">
|
||||
<source>Min</source>
|
||||
<target>分</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownSeconds" resname="countdownSeconds">
|
||||
<source>Sec</source>
|
||||
<target>秒</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownDay" resname="countdownDay">
|
||||
<source>Day</source>
|
||||
<target>曜日</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownHour" resname="countdownHour">
|
||||
<source>Hour</source>
|
||||
<target>時</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownMinute" resname="countdownMinute">
|
||||
<source>Min</source>
|
||||
<target>分</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownSecond" resname="countdownSecond">
|
||||
<source>Sec</source>
|
||||
<target>秒</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="liveCapitalLetter" resname="liveCapitalLetter">
|
||||
<source>Live</source>
|
||||
<target>ライブ</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="watchNow" resname="watchNow">
|
||||
<source>Watch now</source>
|
||||
<target>現在視聴可能</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="seriesHeaderUpcoming" resname="seriesHeaderUpcoming">
|
||||
<source>Upcoming</source>
|
||||
<target>予定</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventRegattaLeaderboardLastScoreUpdate" resname="eventRegattaLeaderboardLastScoreUpdate">
|
||||
<source>Last Score Update</source>
|
||||
<target>前回スコア更新</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventRegattaRaceNotTracked" resname="eventRegattaRaceNotTracked">
|
||||
<source>Not Tracked</source>
|
||||
<target>未追跡</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerJobs" resname="footerJobs">
|
||||
<source>Jobs</source>
|
||||
<target>採用</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerCopyright" resname="footerCopyright">
|
||||
<source>© 2011-2016 SAP Sailing Analytics</source>
|
||||
<target>© 2011-2016 SAP Sailing Analytics</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerLanguage" resname="footerLanguage">
|
||||
<source>SAP Sailing in</source>
|
||||
<target>SAP Sailing -</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerLegal" resname="footerLegal">
|
||||
<source>Legal Disclosure</source>
|
||||
<target>利用規約</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerPrivacy" resname="footerPrivacy">
|
||||
<source>Privacy</source>
|
||||
<target>個人情報保護</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerFeedback" resname="footerFeedback">
|
||||
<source>Feedback</source>
|
||||
<target>フィードバック</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="headerLogo" resname="headerLogo">
|
||||
<source>Sailing Analytics</source>
|
||||
<target>Sailing Analytics</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="headerSearchPlaceholder" resname="headerSearchPlaceholder">
|
||||
<source>Search </source>
|
||||
<target>検索 </target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainEventShowAll" resname="mainEventShowAll">
|
||||
<source>Show All Events</source>
|
||||
<target>全イベント表示</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainEventTitle" resname="mainEventTitle">
|
||||
<source>Latest Events from the Sailing World</source>
|
||||
<target>Sailing World からの最新イベント</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaSubtitle" resname="mainMediaSubtitle">
|
||||
<source>Get lost in the latest and most beautiful impressions from your favorite sailing event.</source>
|
||||
<target>お気に入りのセーリングイベントのすてきな最新画像を楽しんでください。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaTitle" resname="mainMediaTitle">
|
||||
<source>Photographers love Sailing</source>
|
||||
<target>最新のセーリング画像</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaVideosSubtitle" resname="mainMediaVideosSubtitle">
|
||||
<source>Immerse yourself in the world of sailing and check out our latest events for more videos.</source>
|
||||
<target>最新イベントの動画にアクセスしてセーリングの世界に浸ってください。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaVideosTitle" resname="mainMediaVideosTitle">
|
||||
<source>Recent Video Entries</source>
|
||||
<target>最新のセーリング動画</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultHeaderButton" resname="searchResultHeaderButton">
|
||||
<source>Search</source>
|
||||
<target>検索</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultHeaderLabel" resname="searchResultHeaderLabel">
|
||||
<source>Your Search</source>
|
||||
<target>検索対象</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultHeaderPlaceholder" resname="searchResultHeaderPlaceholder">
|
||||
<source>Type in your searchkey</source>
|
||||
<target>検索キーを入力</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultSortNewest" resname="searchResultSortNewest">
|
||||
<source>Recent</source>
|
||||
<target>最新</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsSISHeadline" resname="solutionsSISHeadline">
|
||||
<source>SAP in Sailing</source>
|
||||
<target>SAP in Sailing</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsSAPHeadline" resname="solutionsSAPHeadline">
|
||||
<source>SAP Sailing Analytics</source>
|
||||
<target>SAP Sailing Analytics</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsRaceHeadline" resname="solutionsRaceHeadline">
|
||||
<source>SAP Sailing Race Manager</source>
|
||||
<target>SAP Sailing Race Manager</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsInSightHeadline" resname="solutionsInSightHeadline">
|
||||
<source>SAP Sail InSight</source>
|
||||
<target>SAP Sail InSight</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsBuoyPingerHeadline" resname="solutionsBuoyPingerHeadline">
|
||||
<source>SAP Sailing Buoy Pinger</source>
|
||||
<target>SAP Sailing Buoy Pinger</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsPostHeadline" resname="solutionsPostHeadline">
|
||||
<source>Post-Race Analytics</source>
|
||||
<target>レース後分析</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsTrainingHeadline" resname="solutionsTrainingHeadline">
|
||||
<source>Training Diary</source>
|
||||
<target>トレーニング日記</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsSimulatorHeadline" resname="solutionsSimulatorHeadline">
|
||||
<source>Strategy Simulator</source>
|
||||
<target>戦略シミュレータ</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapInSailing" resname="sapInSailing">
|
||||
<source>SAP in Sailing</source>
|
||||
<target>SAP in Sailing</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing1" resname="contentSapInSailing1">
|
||||
<source>Sailing provides the perfect platform for SAP to showcase solutions and help the sport run like never before. SAP’s involvement in the sport has transformed the sailing experience by providing tools, which:</source>
|
||||
<target>セーリングは、SAP にとってソリューションを紹介するためのプラットフォームとしてうってつけのものであり、これまでになかったやり方でスポーツの運営を支援しています。SAP によるスポーツへの関与は、以下のことを行うツールを提供することによってセーリングから得られる体験を別次元のものに変えました。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing2" resname="contentSapInSailing2">
|
||||
<source>Help sailors analyze performance and optimize strategy</source>
|
||||
<target>パフォーマンスの分析と戦略の最適化でセーラーを支援します</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing3" resname="contentSapInSailing3">
|
||||
<source>Bring fans closer to the action</source>
|
||||
<target>アクションをファンにとって身近なものにします</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing4" resname="contentSapInSailing4">
|
||||
<source>Provide the media with information and insights to deliver a greater informed commentary</source>
|
||||
<target>情報豊富なすばらしい解説を行うための情報とインサイトを報道関係者に提供します</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing5" resname="contentSapInSailing5">
|
||||
<source>SAP has a longstanding involvement with sailing and has established a portfolio spanning across teams and regattas, including:</source>
|
||||
<target>SAP は、長年にわたりセーリングに関与しており、以下のようなチームおよびレガッタと関係を構築してきました。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing6" resname="contentSapInSailing6">
|
||||
<source>Official Technology Partner of Travemünder Woche</source>
|
||||
<target>Travemünder Woche の公式テクノロジーパートナー</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing7" resname="contentSapInSailing7">
|
||||
<source>Technical Partner of the European Sailing Leagues</source>
|
||||
<target>欧州セーリング連盟 (European Sailing Leagues) のテクノロジーパートナー</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing8" resname="contentSapInSailing8">
|
||||
<source>Title sponsor of the SAP Extreme Sailing Team</source>
|
||||
<target>SAP Extreme Sailing Team のタイトルスポンサー</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing9" resname="contentSapInSailing9">
|
||||
<source>Official Technical Partner of the Extreme Sailing Series</source>
|
||||
<target>Extreme Sailing Series の公式テクニカルパートナー</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing10" resname="contentSapInSailing10">
|
||||
<source>Premium Partner of Germany’s national sailing team, Audi Sailing Team Germany</source>
|
||||
<target>ドイツ代表セーリングチームである Audi Sailing Team Germany のプレミアムパートナー</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing11" resname="contentSapInSailing11">
|
||||
<source>Premium Partner of the world’s largest regatta, Kieler Woche (Kiel Week)</source>
|
||||
<target>世界最大のレガッタである Kieler Woche (Kiel Week) のプレミアムパートナー</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing12" resname="contentSapInSailing12">
|
||||
<source>Title sponsor of the SAP 5O5 World Championships</source>
|
||||
<target>SAP 5O5 World Championships のタイトルスポンサー</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingAnalyticsTitle" resname="sapSailingAnalyticsTitle">
|
||||
<source>SAP Sailing Analytics</source>
|
||||
<target>SAP Sailing Analytics</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingAnalytics1" resname="contentSapSailingAnalytics1">
|
||||
<source>By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing.</source>
|
||||
<target>レースランキング、速力、操縦、ベアリングなどに関係するリアルタイム分析を提供することにより、SAP はセーリングという複雑なスポーツを簡略に分かりやすく説明することをお手伝いしています。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingAnalytics2" resname="contentSapSailingAnalytics2">
|
||||
<source>SAP Sailing Analytics provide insights and transparency to the world of sailing by utilizing Cloud and In-Memory Technology, processing GPS and wind measurement data in real time and visualizing contents in various frontends accessible from anywhere.</source>
|
||||
<target>SAP Sailing Analytics は、クラウドおよびインメモリ技術を活用し、リアルタイムで GPS および風計測データを処理し、どこからでもアクセスできるさまざまなフロントエンドでコンテンツを視覚化することによってセーリングの世界にインサイトと透明性を提供します。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingAnalyticsReadMore" resname="sapSailingAnalyticsReadMore">
|
||||
<source>Read More</source>
|
||||
<target>続きを読む</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingRaceManager" resname="sapSailingRaceManager">
|
||||
<source>SAP Sailing Race Manager</source>
|
||||
<target>SAP Sailing Race Manager</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingRaceManager" resname="contentSapSailingRaceManager">
|
||||
<source>The SAP Sailing Race Manager delivers greater efficiency and control to race organizers by automating and simplifying their manual tasks and communication during running sailing regattas. The Race Committee App helps simplify the operation of running and managing race events to help race committees operate smarter.</source>
|
||||
<target>SAP Sailing Race Manager は、セーリングレガッタ運営中にレース組織者が手動で行う作業や連絡業務を自動化/簡略化することによって効率と統制を向上させます。Race Committee アプリは、レースイベントの運営/管理業務を簡略化するのに役立ち、レース委員会がより円滑に運営されるよう支援します。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingRaceManagerReadMore" resname="sapSailingRaceManagerReadMore">
|
||||
<source>Learn More</source>
|
||||
<target>詳細情報</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailInSight" resname="sapSailInSight">
|
||||
<source>SAP Sail InSight</source>
|
||||
<target>SAP Sail InSight</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailInSight" resname="contentSapSailInSight">
|
||||
<source>With the SAP Sail InSight mobile app for iPhone, iPad and Android phones, sailboat racers can manage their regatta participation and performance anywhere and anytime. This app connects to the SAP Sailing Analytics solution and enables racers to sign in to an SAP Sail InSight-enabled regatta, track their location together with performance indicators like speed or distance sailed, and analyze their performance.</source>
|
||||
<target>iPhone、iPad、および Android フォン向け SAP Sail InSight モバイルアプリにより、ヨット競技者はいつでもどこでもレガッタ参加やパフォーマンスを管理することができます。このアプリは SAP Sailing Analytics ソリューションに接続され、競技者が SAP Sail InSight 対応のレガッタへの受付を行い、自分がどこにいるかを艇速や帆走距離などのパフォーマンス指標とともに追跡し、自らのパフォーマンスを分析することを可能にします。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailInSightReadMore" resname="sapSailInSightReadMore">
|
||||
<source>Learn More</source>
|
||||
<target>詳細情報</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingBuoyPinger" resname="sapSailingBuoyPinger">
|
||||
<source>SAP Sailing Buoy Pinger</source>
|
||||
<target>SAP Sailing Buoy Pinger</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingBuoyPinger" resname="contentSapSailingBuoyPinger">
|
||||
<source>With the SAP Sailing Buoy Pinger mobile app for Android phones, sailboat race managers can simplify the positioning of race marks and communication with the mark layers anywhere and anytime. This app connects to the SAP Sailing Analytics solution and allows regatta managers to track the geographical position of their race marks, enabling the use of the SAP Sail InSight mobile app by sailors participating in the regatta.</source>
|
||||
<target>Android フォン向け SAP Sailing Buoy Pinger モバイルアプリにより、ヨットレース運営者はいつでもどこでもレース用のマークの位置決めや、マーク設置担当者とのやり取りを簡略化することができます。このアプリは SAP Sailing Analytics ソリューションに接続され、レガッタ運営者がレース用のマークの地理的位置を追跡することを可能にし、レガッタに参加しているセーラーが SAP Sail InSight モバイルアプリを使用できるようにします。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingBuoyPingerReadMore" resname="sapSailingBuoyPingerReadMore">
|
||||
<source>Learn More</source>
|
||||
<target>詳細情報</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="postRaceAnalytics" resname="postRaceAnalytics">
|
||||
<source>Post-Race Analytics</source>
|
||||
<target>レース後分析</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentPostRaceAnalytics1" resname="contentPostRaceAnalytics1">
|
||||
<source>Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better.</source>
|
||||
<target>セーリングイベントで収集されたデータへのアクセスにより、戦略の策定や帆走の向上に役立つ、セーラーがそのパフォーマンスを評価および分析する機会が提供されます。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentPostRaceAnalytics2" resname="contentPostRaceAnalytics2">
|
||||
<source>SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas.</source>
|
||||
<target>SAP Business Analytics ソリューションは、多くのレガッタおよびレースにわたって履歴データを照会および分析するツールをセーラー、コーチ、ファン、そして報道関係者に提供します。SAP HANA は、こうした人たちが自身のパフォーマンスを最適化し、予定されているレガッタで成功を収める戦略を策定するために簡単、迅速、かつ効率的な方法でパフォーマンスのパターン、傾向、およびセーラーのプロファイルを知ることを可能にします。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="i18nDeSolutionsTrainingHeadline" resname="i18nDeSolutionsTrainingHeadline">
|
||||
<source>SAP Sail Better – STG Training Diary</source>
|
||||
<target>SAP Sail Better – STG Training Diary</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="i18nDeSolutionsTrainingText" resname="i18nDeSolutionsTrainingText">
|
||||
<source>The STG Training Diary supports the daily documentation and analysis of an athlete’s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel.</source>
|
||||
<target>STG Training Diary は、選手の体調、ならびに水上トレーニング、身体的トレーニング、操艇、メンタル、理論、さらに教育や移動などのその他の活動の領域におけるトレーニングへの取り組みの日々の記録および分析をサポートします。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="strategySimulator" resname="strategySimulator">
|
||||
<source>Strategy Simulator</source>
|
||||
<target>戦略シミュレータ</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentStrategySimulator" resname="contentStrategySimulator">
|
||||
<source>Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions.</source>
|
||||
<target>適切な戦略を選択すれば、レース中に大きな競争上の優位性を得ることが可能です。Strategy Simulator により、さまざまな風況および水流に対して最良のセーリング戦略を決定することが容易になります。風と水流をシミュレーションで直ちに変更することができるため、不確かな気象条件に対しても戦略の確かさを簡単に評価することができます。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="strategySimulatorReadMore" resname="strategySimulatorReadMore">
|
||||
<source>Learn More</source>
|
||||
<target>詳細情報</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="impressum" resname="impressum">
|
||||
<source>Imprint</source>
|
||||
<target>刻印</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="lastFix" resname="lastFix">
|
||||
<source>Last fix</source>
|
||||
<target>最終フィックス</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="filterDeviceMappings" resname="filterDeviceMappings">
|
||||
<source>Filter device mappings</source>
|
||||
<target>デバイスマッピングのフィルタリング</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
+441
-43
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-08-12T11:07:17Z" original="/usr/sap/ljs/app/Converter_4178050061048672287/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties" source-language="en" target-language="ru">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-09-29T12:17:08Z" original="/usr/sap/ljs/app/Converter_7623614428299933729/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties" source-language="en" target-language="ru">
|
||||
<header>
|
||||
<skl>
|
||||
<internal-file crc="f6ec166735cc7adb2ddad356f75a3f11" form="base64">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 truncated
|
||||
<internal-file crc="aa58aa0159559141c900793034ac8e1d" form="base64">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 truncated
|
||||
</skl>
|
||||
<phase-group>
|
||||
<phase company-name="SAP AG" date="2016-07-28T14:32:35Z" phase-name="file-creation" process-name="file-creation" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter"/>
|
||||
<phase company-name="SAP AG" date="2016-09-26T08:30:46Z" phase-name="file-creation" process-name="file-creation" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter"/>
|
||||
</phase-group>
|
||||
<tool tool-company="SAP AG" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter" tool-name="TEW: Javascript .properties Flexible File Converter" tool-version="1.1.0"/>
|
||||
</header>
|
||||
@@ -65,7 +65,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="windPanelLabel" resname="windPanelLabel">
|
||||
<source>This is the Wind Panel which so far is completely empty.</source>
|
||||
<target state="translated">Это панель ветров, которая пока что совсем пуста.</target>
|
||||
<target state="signed-off">Это панель ветров, которая пока что совсем пуста.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="refresh" resname="refresh">
|
||||
<source>Refresh</source>
|
||||
@@ -929,7 +929,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="raceIsKnownToStartUpwind" resname="raceIsKnownToStartUpwind">
|
||||
<source>Race starts with upwind leg</source>
|
||||
<target state="translated">Гонка начинается против ветра</target>
|
||||
<target state="signed-off">Гонка начинается против ветра</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="events" resname="events">
|
||||
<source>Events</source>
|
||||
@@ -937,8 +937,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="settingsForComponent" resname="settingsForComponent">
|
||||
<source>Settings for <ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> — параметры</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> — параметры</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="noEventsFound" resname="noEventsFound">
|
||||
<source>No events were found</source>
|
||||
@@ -1002,13 +1001,11 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="competitorPassedMarkAtDate" resname="competitorPassedMarkAtDate">
|
||||
<source><ph id="1">{0}</ph> passed <ph id="2">{1}</ph> at <ph id="3">{2}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> пройдено <ph id="2">{1}</ph> в <ph id="3">{2}</ph></target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> пройдено <ph id="2">{1}</ph> в <ph id="3">{2}</ph></target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="valueForCompetitorAt" resname="valueForCompetitorAt">
|
||||
<source><ph id="1">{0}</ph> at <ph id="2">{1}</ph>: <ph id="3">{2}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> в <ph id="2">{1}</ph>: <ph id="3">{2}</ph></target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> в <ph id="2">{1}</ph>: <ph id="3">{2}</ph></target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="reallyRemoveRace" resname="reallyRemoveRace">
|
||||
<source>Do you really want to remove the race ''<ph id="1">{0}</ph>''? Note: all race logs for this race will also permanently be removed!</source>
|
||||
@@ -1776,7 +1773,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="scoringSchemeLowPointForLeagueOverallLeaderboardDescription" resname="scoringSchemeLowPointForLeagueOverallLeaderboardDescription">
|
||||
<source>Instead of the usual count-back system used for low point schemes to break ties, competitors with equal point sums are compared by comparing the sum of the points they scored across all acts. If this still leaves a tie, the tie is broken by the last act.</source>
|
||||
<target state="translated">Вместо обычной системы обратного отсчета, используемой для разрешения равенства в схемах низких баллов, участники с равными суммами баллов сравниваются по сумме баллов, полученных за все акты. Если равенство сохраняется, оно разрешается по последнему акту.</target>
|
||||
<target state="signed-off">Вместо обычной системы обратного отсчета, используемой для разрешения равенства в схемах низких баллов, участники с равными суммами баллов сравниваются по сумме баллов, полученных за все акты. Если равенство сохраняется, оно разрешается по последнему акту.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="scoringSchemeLowPointTieBreakBasedOnLastSeriesOnly" resname="scoringSchemeLowPointTieBreakBasedOnLastSeriesOnly">
|
||||
<source>Low Point, ties broken based on last series only</source>
|
||||
@@ -1986,6 +1983,30 @@
|
||||
<source>Title</source>
|
||||
<target state="signed-off">Название</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="subtitle" resname="subtitle">
|
||||
<source>Subtitle</source>
|
||||
<target state="signed-off">Подзаголовок</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="copyright" resname="copyright">
|
||||
<source>Copyright</source>
|
||||
<target state="signed-off">Copyright</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="widthInPx" resname="widthInPx">
|
||||
<source>Width (pixel)</source>
|
||||
<target state="signed-off">Ширина (в пикселях)</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="heightInPx" resname="heightInPx">
|
||||
<source>Height (pixel)</source>
|
||||
<target state="signed-off">Высота (в пикселях)</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="tags" resname="tags">
|
||||
<source>Tags</source>
|
||||
<target state="signed-off">Теги</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="size" resname="size">
|
||||
<source>Size</source>
|
||||
<target state="signed-off">Размер</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="duration" resname="duration">
|
||||
<source>Duration (h:mm:ss.ms)</source>
|
||||
<target state="signed-off">Длительность (ч:мм:сс.мс)</target>
|
||||
@@ -2140,8 +2161,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="competitorRegattaDataAfterRaceN" resname="competitorRegattaDataAfterRaceN">
|
||||
<source><ph id="1">{0}</ph> after race <ph id="2">{1}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> после гонки <ph id="2">{1}</ph></target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> после гонки <ph id="2">{1}</ph></target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="rankChart" resname="rankChart">
|
||||
<source>Ranking</source>
|
||||
@@ -3729,7 +3749,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="rerunQueryAfterRefresh" resname="rerunQueryAfterRefresh">
|
||||
<source>Rerun query after refresh</source>
|
||||
<target state="translated">Повторить запрос после обновления</target>
|
||||
<target state="signed-off">Повторить запрос после обновления</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="refreshIntervalMustntBeEmpty" resname="refreshIntervalMustntBeEmpty">
|
||||
<source>Refresh interval mustn''t be empty</source>
|
||||
@@ -3997,7 +4017,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="errorImportingIgtimiWind" resname="errorImportingIgtimiWind">
|
||||
<source>Error importing wind data from Igtimi: <ph id="1">{0}</ph></source>
|
||||
<target state="translated">Ошибка при импорте данных о ветре из Igtimi: <ph id="1">{0}</ph></target>
|
||||
<target state="signed-off">Ошибка при импорте данных о ветре из Igtimi: <ph id="1">{0}</ph></target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="resultFromIgtimiWindImport" resname="resultFromIgtimiWindImport">
|
||||
<source>The following number of fixes were imported for the listed races: <ph id="1">{0}</ph></source>
|
||||
@@ -4005,13 +4025,11 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="timeToStart" resname="timeToStart">
|
||||
<source><ph id="1">{0}</ph> to start</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> до старта</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> до старта</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="timeSinceStart" resname="timeSinceStart">
|
||||
<source><ph id="1">{0}</ph> since start</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> от старта</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> от старта</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="distanceToLine" resname="distanceToLine">
|
||||
<source>Distance to start line</source>
|
||||
@@ -4343,8 +4361,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventSharingShortText" resname="eventSharingShortText">
|
||||
<source><ph id="1">{0}</ph> in <ph id="2">{1}</ph> on <ph id="3">{2}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> в <ph id="2">{1}</ph> на <ph id="3">{2}</ph></target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> в <ph id="2">{1}</ph> на <ph id="3">{2}</ph></target>
|
||||
<note annotates="source" from="Developer">String eventSharingShortText(String eventName, String venue, String dateString);</note>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventSharingLongText" resname="eventSharingLongText">
|
||||
@@ -4359,9 +4376,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="seriesSharingShortText" resname="seriesSharingShortText">
|
||||
<source><ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>
|
||||
</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph></target>
|
||||
<note annotates="source" from="Developer">String seriesSharingShortText(String seriesName);</note>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="competitorsAnalytics" resname="competitorsAnalytics">
|
||||
@@ -4520,6 +4535,10 @@
|
||||
<source>Use start time inference from start mark passings</source>
|
||||
<target state="signed-off">Использовать вывод о времени старта из прохождений стартовой отметки</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="controlTrackingFromStartAndFinishTimes" resname="controlTrackingFromStartAndFinishTimes">
|
||||
<source>Control tracking from start and finish times</source>
|
||||
<target>Контролировать отслеживание от времени старта и финиша</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="numberOfQueueMessagesSent" resname="numberOfQueueMessagesSent">
|
||||
<source>Number of queue messages sent</source>
|
||||
<target state="signed-off">Число отправленных сообщений очереди</target>
|
||||
@@ -4614,8 +4633,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mediaSelectVideoCaption" resname="mediaSelectVideoCaption">
|
||||
<source><ph id="1">{0}</ph> Videos</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> видео</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> видео</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mediaSelectVideoTooltip" resname="mediaSelectVideoTooltip">
|
||||
<source>Click to select video</source>
|
||||
@@ -5287,8 +5305,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="startingIn" resname="startingIn">
|
||||
<source><ph id="1">{0}</ph> starts in</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> начинается через</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> начинается через</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="raceIsPlanned" resname="raceIsPlanned">
|
||||
<source>Planned</source>
|
||||
@@ -5352,7 +5369,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="orcPerformanceCurveRankingMetricDescription" resname="orcPerformanceCurveRankingMetricDescription">
|
||||
<source>ORC Performance Curve: Sophisticated handicapping scheme that awards time allowances based on a VPP/polar assuming pre-defined legs'' angles to the wind;\nbased on these allowances, an "implied wind" is calculated which is the basis for ranking.\nImplied wind can be calculated at any time in the race and is therefore the basis for in-race ranking. </source>
|
||||
<target state="translated">Кривая эффективности ORC: сложная схема гандикапа, предоставляющая фору с учетом VPP/полярных данных для предварительно определенных углов отрезков к ветру;\nна основе этих допусков рассчитывается "подразумеваемый ветер", используемый как основа для ранжирования.\nПодразумеваемый ветер можно рассчитать в любое время в ходе гонки, поэтому он является основой для ранжирования в гонке.</target>
|
||||
<target state="signed-off">Кривая эффективности ORC: сложная схема гандикапа, предоставляющая фору с учетом VPP/полярных данных для предварительно определенных углов отрезков к ветру;\nна основе этих допусков рассчитывается "подразумеваемый ветер", используемый как основа для ранжирования.\nПодразумеваемый ветер можно рассчитать в любое время в ходе гонки, поэтому он является основой для ранжирования в гонке.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="timeOnTimeAndDistanceRankingMetricDescription" resname="timeOnTimeAndDistanceRankingMetricDescription">
|
||||
<source>Time-on-Time / Time-on-Distance: Final ranking by calculated time;\ntime is calculated by optionally applying a factor to the actual time (defaulting to 1.0)\nand subtracting an allowance in seconds per nautical mile,\napplied to the course length.\nIn-race ranks based on expected arrival at fastest boat's current position\nassuming current leg's average VMG/VMC.</source>
|
||||
@@ -5492,13 +5509,11 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="minutesAgo" resname="minutesAgo">
|
||||
<source><ph id="1">{0}</ph> min ago</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> мин. назад</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> мин. назад</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="hoursAgo" resname="hoursAgo">
|
||||
<source><ph id="1">{0}</ph> h ago</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> ч. назад</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> ч. назад</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="winner" resname="winner">
|
||||
<source>Winner</source>
|
||||
@@ -5534,8 +5549,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="degreesToWind" resname="degreesToWind">
|
||||
<source><ph id="1">{0}</ph>° to wind</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>° к ветру</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>° к ветру</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="miniLeeaderboardLegendText" resname="miniLeeaderboardLegendText">
|
||||
<source>Shows the points along with the number of races per competitor</source>
|
||||
@@ -5647,7 +5661,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="plainResultsPresenter" resname="plainResultsPresenter">
|
||||
<source>Plain Results Presenter</source>
|
||||
<target state="translated">Презентатор простых результатов</target>
|
||||
<target state="signed-off">Презентатор простых результатов</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="resultsChart" resname="resultsChart">
|
||||
<source>Results Chart</source>
|
||||
@@ -6025,25 +6039,25 @@
|
||||
<source>utm_source=sapsailing&utm_medium=solutions&utm_content=2016.02&utm_campaign=solutions&pcampaignid=2016.sapsailing.solutions</source>
|
||||
<target state="signed-off">utm_source=sapsailing&utm_medium=solutions&utm_content=2016.02&utm_campaign=solutions&pcampaignid=2016.sapsailing.solutions</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreTrackingApp" resname="playstoreTrackingApp">
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreInsightApp" resname="playstoreInsightApp">
|
||||
<source>https://play.google.com/store/apps/details?id=com.sap.sailing.android.tracking.app</source>
|
||||
<target state="signed-off">https://play.google.com/store/apps/details?id=com.sap.sailing.android.tracking.app</target>
|
||||
<target>https://play.google.com/store/apps/details?id=com.sap.sailing.android.tracking.app</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreRacecommitteeApp" resname="playstoreRacecommitteeApp">
|
||||
<source>https://play.google.com/store/apps/details?id=com.sap.sailing.racecommittee.app</source>
|
||||
<target state="signed-off">https://play.google.com/store/apps/details?id=com.sap.sailing.racecommittee.app</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playStoreBuoypositioningApp" resname="playStoreBuoypositioningApp">
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playStoreBuoyPingerApp" resname="playStoreBuoyPingerApp">
|
||||
<source>https://play.google.com/store/apps/details?id=com.sap.sailing.android.buoy.positioning.app</source>
|
||||
<target state="signed-off">https://play.google.com/store/apps/details?id=com.sap.sailing.android.buoy.positioning.app</target>
|
||||
<target>https://play.google.com/store/apps/details?id=com.sap.sailing.android.buoy.positioning.app</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreBadge" resname="playstoreBadge">
|
||||
<source>https://play.google.com/intl/en/badges/images/generic/en-play-badge.png</source>
|
||||
<target state="signed-off">https://play.google.com/intl/en/badges/images/generic/en-play-badge.png</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="appstoreSapSailingInsight" resname="appstoreSapSailingInsight">
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="appstoreSapSailInsight" resname="appstoreSapSailInsight">
|
||||
<source>http://appstore.com/sapsailinsight</source>
|
||||
<target state="signed-off">http://appstore.com/sapsailinsight</target>
|
||||
<target>http://appstore.com/sapsailinsight</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="appstoreStgTrainingstagebuch" resname="appstoreStgTrainingstagebuch">
|
||||
<source>http://appstore.com/stgtrainingstagebuch</source>
|
||||
@@ -6441,6 +6455,390 @@
|
||||
<source>Maximum number of discards</source>
|
||||
<target state="signed-off">Максимальное число исключений</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="notificationRegattaConfigurationUpdatedUsingByMarks" resname="notificationRegattaConfigurationUpdatedUsingByMarks">
|
||||
<source>Active regatta configuration was set, using the "By Marks" course designer.</source>
|
||||
<target state="signed-off">Активная конфигурация регаты была настроена с использованием дизайнера курса "По отметкам".</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="warningOverrideRegattaConfigurationCourseDesignerToByMarks" resname="warningOverrideRegattaConfigurationCourseDesignerToByMarks">
|
||||
<source>Active regatta configuration already exists, but with the wrong course designer setting.\nWould you like to override course designer setting to "By Marks"?</source>
|
||||
<target state="signed-off">Активная конфигурация регаты уже существует, но с неверно выбранным дизайнером курса.\nПереопределить выбор дизайнера курса на "По отметкам"?</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="allRacesHaveBeenDenoted" resname="allRacesHaveBeenDenoted">
|
||||
<source>All races have been denoted for racelog tracking.</source>
|
||||
<target state="signed-off">Отслеживание журнала всех гонок отменено.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="chartSelectionHint" resname="chartSelectionHint">
|
||||
<source>Hint: You can also use the leaderboard (on the LEADERBOARD tab) to select the competitors displayed in the chart. </source>
|
||||
<target>Совет: таблицу лидеров (на вкладке ТАБЛИЦА ЛИДЕРОВ) также можно использовать для выбора участников, отображаемых в диаграмме. </target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="chooseALanguage" resname="chooseALanguage">
|
||||
<source>Choose a language</source>
|
||||
<target>Выбор языка</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutions" resname="solutions">
|
||||
<source>Solutions</source>
|
||||
<target>Решения</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="blog" resname="blog">
|
||||
<source>Blog</source>
|
||||
<target>Блог</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="officalEventWebsite" resname="officalEventWebsite">
|
||||
<source>Official event website</source>
|
||||
<target>Официальный веб-сайт события</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="moreInfo" resname="moreInfo">
|
||||
<source>More info</source>
|
||||
<target>Больше сведений</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="viewAnalysis" resname="viewAnalysis">
|
||||
<source>View analysis </source>
|
||||
<target>Просмотреть анализ </target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="overallLeaderboard" resname="overallLeaderboard">
|
||||
<source>Overall leaderboard</source>
|
||||
<target>Общая таблица лидеров</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="pleaseTryAgain" resname="pleaseTryAgain">
|
||||
<source>Please try again...</source>
|
||||
<target>Повторите попытку...</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="reloadPage" resname="reloadPage">
|
||||
<source>Reload page</source>
|
||||
<target>Перезагрузить страницу</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="errorMessageLoadingData" resname="errorMessageLoadingData">
|
||||
<source>An error occured while loading the data for this page.</source>
|
||||
<target>При загрузке данных для этой страницы возникла ошибка.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="regattaDetails" resname="regattaDetails">
|
||||
<source>Regatta details</source>
|
||||
<target>Подробности регаты</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="chooseChartType" resname="chooseChartType">
|
||||
<source>Choose chart type</source>
|
||||
<target>Выберите тип диаграммы</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="whatsNew" resname="whatsNew">
|
||||
<source>What''s new</source>
|
||||
<target>Новые возможности</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailing" resname="sapSailing">
|
||||
<source>SAP Sailing</source>
|
||||
<target>SAP Sailing</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="search" resname="search">
|
||||
<source>Search</source>
|
||||
<target>Поиск</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownStartingInDays" resname="countdownStartingInDays">
|
||||
<source>Days</source>
|
||||
<target>дн.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownDays" resname="countdownDays">
|
||||
<source>Days</source>
|
||||
<target>дн.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownHours" resname="countdownHours">
|
||||
<source>Hrs</source>
|
||||
<target>ч.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownMinutes" resname="countdownMinutes">
|
||||
<source>Min</source>
|
||||
<target>мин.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownSeconds" resname="countdownSeconds">
|
||||
<source>Sec</source>
|
||||
<target>сек.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownDay" resname="countdownDay">
|
||||
<source>Day</source>
|
||||
<target>дн.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownHour" resname="countdownHour">
|
||||
<source>Hour</source>
|
||||
<target>ч.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownMinute" resname="countdownMinute">
|
||||
<source>Min</source>
|
||||
<target>мин.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownSecond" resname="countdownSecond">
|
||||
<source>Sec</source>
|
||||
<target>сек.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="liveCapitalLetter" resname="liveCapitalLetter">
|
||||
<source>Live</source>
|
||||
<target>Активно</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="watchNow" resname="watchNow">
|
||||
<source>Watch now</source>
|
||||
<target>Смотреть сейчас</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="seriesHeaderUpcoming" resname="seriesHeaderUpcoming">
|
||||
<source>Upcoming</source>
|
||||
<target>Скоро</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventRegattaLeaderboardLastScoreUpdate" resname="eventRegattaLeaderboardLastScoreUpdate">
|
||||
<source>Last Score Update</source>
|
||||
<target>Последнее обновление оценок</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventRegattaRaceNotTracked" resname="eventRegattaRaceNotTracked">
|
||||
<source>Not Tracked</source>
|
||||
<target>Не отслеживается</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerJobs" resname="footerJobs">
|
||||
<source>Jobs</source>
|
||||
<target>Работа</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerCopyright" resname="footerCopyright">
|
||||
<source>© 2011-2016 SAP Sailing Analytics</source>
|
||||
<target>© SAP Sailing Analytics, 2011–2016.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerLanguage" resname="footerLanguage">
|
||||
<source>SAP Sailing in</source>
|
||||
<target>Язык SAP Sailing</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerLegal" resname="footerLegal">
|
||||
<source>Legal Disclosure</source>
|
||||
<target>Раскрытие юридической информации</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerPrivacy" resname="footerPrivacy">
|
||||
<source>Privacy</source>
|
||||
<target>Конфиденциальность</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerFeedback" resname="footerFeedback">
|
||||
<source>Feedback</source>
|
||||
<target>Обратная связь</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="headerLogo" resname="headerLogo">
|
||||
<source>Sailing Analytics</source>
|
||||
<target>Sailing Analytics</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="headerSearchPlaceholder" resname="headerSearchPlaceholder">
|
||||
<source>Search </source>
|
||||
<target>Поиск </target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainEventShowAll" resname="mainEventShowAll">
|
||||
<source>Show All Events</source>
|
||||
<target>Показать все события</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainEventTitle" resname="mainEventTitle">
|
||||
<source>Latest Events from the Sailing World</source>
|
||||
<target>Последние события в мире парусного спорта</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaSubtitle" resname="mainMediaSubtitle">
|
||||
<source>Get lost in the latest and most beautiful impressions from your favorite sailing event.</source>
|
||||
<target>Погрузитесь в новейшие и прекраснейшие впечатления от избранного события в мире парусного спорта.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaTitle" resname="mainMediaTitle">
|
||||
<source>Photographers love Sailing</source>
|
||||
<target>Фотографы любят паруса</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaVideosSubtitle" resname="mainMediaVideosSubtitle">
|
||||
<source>Immerse yourself in the world of sailing and check out our latest events for more videos.</source>
|
||||
<target>Погрузитесь в мир парусного спорта и просмотрите другие видео наших последних событий.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaVideosTitle" resname="mainMediaVideosTitle">
|
||||
<source>Recent Video Entries</source>
|
||||
<target>Последние видеозаписи</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultHeaderButton" resname="searchResultHeaderButton">
|
||||
<source>Search</source>
|
||||
<target>Поиск</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultHeaderLabel" resname="searchResultHeaderLabel">
|
||||
<source>Your Search</source>
|
||||
<target>Ваш поиск</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultHeaderPlaceholder" resname="searchResultHeaderPlaceholder">
|
||||
<source>Type in your searchkey</source>
|
||||
<target>Введите ключ поиска</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultSortNewest" resname="searchResultSortNewest">
|
||||
<source>Recent</source>
|
||||
<target>Недавние</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsSISHeadline" resname="solutionsSISHeadline">
|
||||
<source>SAP in Sailing</source>
|
||||
<target>SAP в парусном спорте</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsSAPHeadline" resname="solutionsSAPHeadline">
|
||||
<source>SAP Sailing Analytics</source>
|
||||
<target>SAP Sailing Analytics</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsRaceHeadline" resname="solutionsRaceHeadline">
|
||||
<source>SAP Sailing Race Manager</source>
|
||||
<target>SAP Sailing Race Manager</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsInSightHeadline" resname="solutionsInSightHeadline">
|
||||
<source>SAP Sail InSight</source>
|
||||
<target>SAP Sail InSight</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsBuoyPingerHeadline" resname="solutionsBuoyPingerHeadline">
|
||||
<source>SAP Sailing Buoy Pinger</source>
|
||||
<target>SAP Sailing Buoy Pinger</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsPostHeadline" resname="solutionsPostHeadline">
|
||||
<source>Post-Race Analytics</source>
|
||||
<target>Аналитика после гонки</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsTrainingHeadline" resname="solutionsTrainingHeadline">
|
||||
<source>Training Diary</source>
|
||||
<target>Дневник тренировок</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsSimulatorHeadline" resname="solutionsSimulatorHeadline">
|
||||
<source>Strategy Simulator</source>
|
||||
<target>Симулятор стратегии</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapInSailing" resname="sapInSailing">
|
||||
<source>SAP in Sailing</source>
|
||||
<target>SAP в парусном спорте</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing1" resname="contentSapInSailing1">
|
||||
<source>Sailing provides the perfect platform for SAP to showcase solutions and help the sport run like never before. SAP’s involvement in the sport has transformed the sailing experience by providing tools, which:</source>
|
||||
<target>Парусный спорт предоставляет отличную платформу для демонстрации решений SAP и беспрецедентной помощи развитию спорта. Вовлеченность SAP преобразила парусный спорт, предоставив инструменты, которые:</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing2" resname="contentSapInSailing2">
|
||||
<source>Help sailors analyze performance and optimize strategy</source>
|
||||
<target>Помогают мореходам анализировать эффективность и оптимизировать стратегию.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing3" resname="contentSapInSailing3">
|
||||
<source>Bring fans closer to the action</source>
|
||||
<target>Делают болельщиков ближе к действию.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing4" resname="contentSapInSailing4">
|
||||
<source>Provide the media with information and insights to deliver a greater informed commentary</source>
|
||||
<target>Предоставляют информацию и аналитику для более информированного комментирования.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing5" resname="contentSapInSailing5">
|
||||
<source>SAP has a longstanding involvement with sailing and has established a portfolio spanning across teams and regattas, including:</source>
|
||||
<target>За немалое время причастности к парусному спорту компанией SAP накоплено солидное портфолио сотрудничества с разными командами регатами, включая:</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing6" resname="contentSapInSailing6">
|
||||
<source>Official Technology Partner of Travemünder Woche</source>
|
||||
<target>Официальный технологический партнер Travemünder Woche</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing7" resname="contentSapInSailing7">
|
||||
<source>Technical Partner of the European Sailing Leagues</source>
|
||||
<target>Технический партнер Европейской лиги парусного спорта</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing8" resname="contentSapInSailing8">
|
||||
<source>Title sponsor of the SAP Extreme Sailing Team</source>
|
||||
<target>Титульный спонсор команды SAP Extreme Sailing Team</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing9" resname="contentSapInSailing9">
|
||||
<source>Official Technical Partner of the Extreme Sailing Series</source>
|
||||
<target>Официальный технический партнер серии Extreme Sailing Series</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing10" resname="contentSapInSailing10">
|
||||
<source>Premium Partner of Germany’s national sailing team, Audi Sailing Team Germany</source>
|
||||
<target>Премиальный партнер национальной команды Германии по парусному спорту, Audi Sailing Team Germany</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing11" resname="contentSapInSailing11">
|
||||
<source>Premium Partner of the world’s largest regatta, Kieler Woche (Kiel Week)</source>
|
||||
<target>Премиальный партнер крупнейшей в мире регаты Kieler Woche (Кильская неделя)</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing12" resname="contentSapInSailing12">
|
||||
<source>Title sponsor of the SAP 5O5 World Championships</source>
|
||||
<target>Титульный спонсор чемпионатов мира SAP 5O5</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingAnalyticsTitle" resname="sapSailingAnalyticsTitle">
|
||||
<source>SAP Sailing Analytics</source>
|
||||
<target>SAP Sailing Analytics</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingAnalytics1" resname="contentSapSailingAnalytics1">
|
||||
<source>By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing.</source>
|
||||
<target>Предоставляя аналитику по данным о рангах в гонке, скоростях, маневрах, ветрах и т. д. в режиме реального времени, SAP помогает упростить и демистифицировать сложный парусный спорт.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingAnalytics2" resname="contentSapSailingAnalytics2">
|
||||
<source>SAP Sailing Analytics provide insights and transparency to the world of sailing by utilizing Cloud and In-Memory Technology, processing GPS and wind measurement data in real time and visualizing contents in various frontends accessible from anywhere.</source>
|
||||
<target>SAP Sailing Analytics делает мир парусного спорта понятным и прозрачным, используя облако и технологию In-Memory, обработку данных GPS и параметров ветра в реальном времени, а также визуализацию контекста в разных пользовательских интерфейсах, доступных где угодно.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingAnalyticsReadMore" resname="sapSailingAnalyticsReadMore">
|
||||
<source>Read More</source>
|
||||
<target>См. также</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingRaceManager" resname="sapSailingRaceManager">
|
||||
<source>SAP Sailing Race Manager</source>
|
||||
<target>SAP Sailing Race Manager</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingRaceManager" resname="contentSapSailingRaceManager">
|
||||
<source>The SAP Sailing Race Manager delivers greater efficiency and control to race organizers by automating and simplifying their manual tasks and communication during running sailing regattas. The Race Committee App helps simplify the operation of running and managing race events to help race committees operate smarter.</source>
|
||||
<target>Приложение SAP Sailing Race Manager повышает уровень эффективности и контроля для организаторов гонки за счет автоматизации и упрощения выполняемых вручную задач и общения во время проведения парусных регат. Приложение Race Committee помогает упростить проведение событий и управление ими, освобождая для оргкомитета время на лучшую проработку деталей.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingRaceManagerReadMore" resname="sapSailingRaceManagerReadMore">
|
||||
<source>Learn More</source>
|
||||
<target>Узнать больше</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailInSight" resname="sapSailInSight">
|
||||
<source>SAP Sail InSight</source>
|
||||
<target>SAP Sail InSight</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailInSight" resname="contentSapSailInSight">
|
||||
<source>With the SAP Sail InSight mobile app for iPhone, iPad and Android phones, sailboat racers can manage their regatta participation and performance anywhere and anytime. This app connects to the SAP Sailing Analytics solution and enables racers to sign in to an SAP Sail InSight-enabled regatta, track their location together with performance indicators like speed or distance sailed, and analyze their performance.</source>
|
||||
<target>С помощью мобильного приложения SAP Sail InSight для смартфонов iPhone, iPad и Android яхтсмены гонок могут управлять своим участием и эффективностью в регате откуда и когда угодно. Это приложение подключается к решению SAP Sailing Analytics и позволяет яхтсменам выполнять вход в регаты, использующие SAP Sail InSight, отслеживать свое местоположение вместе с индикаторами эффективности, такими как скорость или пройденное расстояние, а также анализировать эффективность.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailInSightReadMore" resname="sapSailInSightReadMore">
|
||||
<source>Learn More</source>
|
||||
<target>Узнать больше</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingBuoyPinger" resname="sapSailingBuoyPinger">
|
||||
<source>SAP Sailing Buoy Pinger</source>
|
||||
<target>SAP Sailing Buoy Pinger</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingBuoyPinger" resname="contentSapSailingBuoyPinger">
|
||||
<source>With the SAP Sailing Buoy Pinger mobile app for Android phones, sailboat race managers can simplify the positioning of race marks and communication with the mark layers anywhere and anytime. This app connects to the SAP Sailing Analytics solution and allows regatta managers to track the geographical position of their race marks, enabling the use of the SAP Sail InSight mobile app by sailors participating in the regatta.</source>
|
||||
<target>Мобильное приложение SAP Sailing Buoy Pinger для смартфонов Android позволяет руководителям парусных гонок упростить позиционирование отметок и общение с установщиками отметок откуда и когда угодно. Это приложение подключается к решению SAP Sailing Analytics и позволяет руководителям гонок отслеживать географическое местоположение гоночных отметок, обеспечивая использование мобильного приложения SAP Sail InSight для яхтсменов, участвующих в регате.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingBuoyPingerReadMore" resname="sapSailingBuoyPingerReadMore">
|
||||
<source>Learn More</source>
|
||||
<target>Узнать больше</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="postRaceAnalytics" resname="postRaceAnalytics">
|
||||
<source>Post-Race Analytics</source>
|
||||
<target>Аналитика после гонки</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentPostRaceAnalytics1" resname="contentPostRaceAnalytics1">
|
||||
<source>Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better.</source>
|
||||
<target>Доступ к данным, собранным на парусных событиях, дает мореходам возможность оценить и проанализировать свои показатели, помогая разрабатывать стратегии и повышать мастерство.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentPostRaceAnalytics2" resname="contentPostRaceAnalytics2">
|
||||
<source>SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas.</source>
|
||||
<target>Решения SAP Business Analytics предоставляют мореходам, тренерам, болельщикам и СМИ инструменты для просмотра и анализа исторических данных по множеству регат и гонок. SAP HANA позволяет изучать паттерны эффективности, тенденции и профили мореходов простым, быстрым и эффективным образом для оптимизации своих показателей и разработки успешных стратегий на будущие регаты.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="i18nDeSolutionsTrainingHeadline" resname="i18nDeSolutionsTrainingHeadline">
|
||||
<source>SAP Sail Better – STG Training Diary</source>
|
||||
<target>SAP Sail Better – Дневник тренировок STG</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="i18nDeSolutionsTrainingText" resname="i18nDeSolutionsTrainingText">
|
||||
<source>The STG Training Diary supports the daily documentation and analysis of an athlete’s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel.</source>
|
||||
<target>Дневник тренировок STG поддерживает ежедневное документирования и анализ физического состояния атлета и его усилий в тренировках на воде, физической подготовке, работе с лодкой, моральной, теоретической подготовке, а также других видах деятельности, таких как образование и путешествия.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="strategySimulator" resname="strategySimulator">
|
||||
<source>Strategy Simulator</source>
|
||||
<target>Симулятор стратегии</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentStrategySimulator" resname="contentStrategySimulator">
|
||||
<source>Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions.</source>
|
||||
<target>Выбор правильной стратегии может обеспечить большое конкурентное преимущество во время гонки. Симулятор стратегии упрощает определение лучшей стратегии хождения под парусом для разных атмосферных условий и водных течений. Возможность мгновенного изменения ветра и течения в симуляции позволяет легко оценить надежность стратегии даже для неопределенных погодных условий.</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="strategySimulatorReadMore" resname="strategySimulatorReadMore">
|
||||
<source>Learn More</source>
|
||||
<target>Узнать больше</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="impressum" resname="impressum">
|
||||
<source>Imprint</source>
|
||||
<target>Печать</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="lastFix" resname="lastFix">
|
||||
<source>Last fix</source>
|
||||
<target>Последний замер</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="filterDeviceMappings" resname="filterDeviceMappings">
|
||||
<source>Filter device mappings</source>
|
||||
<target>Фильтровать сопоставления устройств</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
+443
-50
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-08-12T11:07:24Z" original="/usr/sap/ljs/app/Converter_4178050061048672287/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties" source-language="en" target-language="zh-CN">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-09-29T12:17:24Z" original="/usr/sap/ljs/app/Converter_7623614428299933729/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties" source-language="en" target-language="zh-CN">
|
||||
<header>
|
||||
<skl>
|
||||
<internal-file crc="f6ec166735cc7adb2ddad356f75a3f11" form="base64">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 truncated
|
||||
<internal-file crc="aa58aa0159559141c900793034ac8e1d" form="base64">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 truncated
|
||||
</skl>
|
||||
<phase-group>
|
||||
<phase company-name="SAP AG" date="2016-07-28T14:32:35Z" phase-name="file-creation" process-name="file-creation" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter"/>
|
||||
<phase company-name="SAP AG" date="2016-09-26T08:30:46Z" phase-name="file-creation" process-name="file-creation" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter"/>
|
||||
</phase-group>
|
||||
<tool tool-company="SAP AG" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter" tool-name="TEW: Javascript .properties Flexible File Converter" tool-version="1.1.0"/>
|
||||
</header>
|
||||
@@ -937,8 +937,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="settingsForComponent" resname="settingsForComponent">
|
||||
<source>Settings for <ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>设置</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>设置</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="noEventsFound" resname="noEventsFound">
|
||||
<source>No events were found</source>
|
||||
@@ -1002,13 +1001,11 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="competitorPassedMarkAtDate" resname="competitorPassedMarkAtDate">
|
||||
<source><ph id="1">{0}</ph> passed <ph id="2">{1}</ph> at <ph id="3">{2}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>于<ph id="3">{2}</ph>越过<ph id="2">{1}</ph></target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>于<ph id="3">{2}</ph>越过<ph id="2">{1}</ph></target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="valueForCompetitorAt" resname="valueForCompetitorAt">
|
||||
<source><ph id="1">{0}</ph> at <ph id="2">{1}</ph>: <ph id="3">{2}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>(于<ph id="2">{1}</ph>): <ph id="3">{2}</ph></target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>(于<ph id="2">{1}</ph>): <ph id="3">{2}</ph></target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="reallyRemoveRace" resname="reallyRemoveRace">
|
||||
<source>Do you really want to remove the race ''<ph id="1">{0}</ph>''? Note: all race logs for this race will also permanently be removed!</source>
|
||||
@@ -1124,7 +1121,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="clickAndDragToZoomIn" resname="clickAndDragToZoomIn">
|
||||
<source>Click and drag in the plot area to zoom in</source>
|
||||
<target state="translated">单击并拖动绘图区以放大</target>
|
||||
<target state="signed-off">单击并拖动绘图区以放大</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="windSpeed" resname="windSpeed">
|
||||
<source>Wind speed (kts)</source>
|
||||
@@ -1986,6 +1983,30 @@
|
||||
<source>Title</source>
|
||||
<target state="signed-off">标题</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="subtitle" resname="subtitle">
|
||||
<source>Subtitle</source>
|
||||
<target state="signed-off">副标题</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="copyright" resname="copyright">
|
||||
<source>Copyright</source>
|
||||
<target state="signed-off">版权</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="widthInPx" resname="widthInPx">
|
||||
<source>Width (pixel)</source>
|
||||
<target state="signed-off">宽度(像素)</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="heightInPx" resname="heightInPx">
|
||||
<source>Height (pixel)</source>
|
||||
<target state="signed-off">高度(像素)</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="tags" resname="tags">
|
||||
<source>Tags</source>
|
||||
<target state="signed-off">标记</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="size" resname="size">
|
||||
<source>Size</source>
|
||||
<target state="signed-off">大小</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="duration" resname="duration">
|
||||
<source>Duration (h:mm:ss.ms)</source>
|
||||
<target state="signed-off">持续时间 (h:mm:ss.ms)</target>
|
||||
@@ -2140,8 +2161,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="competitorRegattaDataAfterRaceN" resname="competitorRegattaDataAfterRaceN">
|
||||
<source><ph id="1">{0}</ph> after race <ph id="2">{1}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> 比赛轮次后 <ph id="2">{1}</ph></target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> 比赛轮次后 <ph id="2">{1}</ph></target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="rankChart" resname="rankChart">
|
||||
<source>Ranking</source>
|
||||
@@ -3501,7 +3521,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="groupBy" resname="groupBy">
|
||||
<source>Group by</source>
|
||||
<target state="translated">分组方式</target>
|
||||
<target state="signed-off">分组方式</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="statisticToCalculate" resname="statisticToCalculate">
|
||||
<source>Calculate statistic</source>
|
||||
@@ -3509,8 +3529,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="queryResultsChartSubtitle" resname="queryResultsChartSubtitle">
|
||||
<source>Worked through <ph id="1">{0}</ph> data entries in <ph id="2">{1}</ph> seconds</source>
|
||||
<target state="signed-off">
|
||||
<ph id="2">{1}</ph>秒内处理<ph id="1">{0}</ph>个数据条目</target>
|
||||
<target state="signed-off"><ph id="2">{1}</ph>秒内处理<ph id="1">{0}</ph>个数据条目</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="noQuerySelected" resname="noQuerySelected">
|
||||
<source>No query selected</source>
|
||||
@@ -3778,7 +3797,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="courseDesignerMode" resname="courseDesignerMode">
|
||||
<source>Course designer</source>
|
||||
<target state="signed-off">场地设计师</target>
|
||||
<target state="signed-off">场地设计器</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="racingProcedure" resname="racingProcedure">
|
||||
<source>Racing procedure</source>
|
||||
@@ -4006,13 +4025,11 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="timeToStart" resname="timeToStart">
|
||||
<source><ph id="1">{0}</ph> to start</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> - 开始</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> - 开始</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="timeSinceStart" resname="timeSinceStart">
|
||||
<source><ph id="1">{0}</ph> since start</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph> - 开始后</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph> - 开始后</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="distanceToLine" resname="distanceToLine">
|
||||
<source>Distance to start line</source>
|
||||
@@ -4344,9 +4361,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventSharingShortText" resname="eventSharingShortText">
|
||||
<source><ph id="1">{0}</ph> in <ph id="2">{1}</ph> on <ph id="3">{2}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="3">{2}</ph>
|
||||
<ph id="2">{1}</ph>中的<ph id="1">{0}</ph></target>
|
||||
<target state="signed-off"><ph id="3">{2}</ph><ph id="2">{1}</ph>中的<ph id="1">{0}</ph></target>
|
||||
<note annotates="source" from="Developer">String eventSharingShortText(String eventName, String venue, String dateString);</note>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventSharingLongText" resname="eventSharingLongText">
|
||||
@@ -4361,9 +4376,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="seriesSharingShortText" resname="seriesSharingShortText">
|
||||
<source><ph id="1">{0}</ph></source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>
|
||||
</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph></target>
|
||||
<note annotates="source" from="Developer">String seriesSharingShortText(String seriesName);</note>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="competitorsAnalytics" resname="competitorsAnalytics">
|
||||
@@ -4522,6 +4535,10 @@
|
||||
<source>Use start time inference from start mark passings</source>
|
||||
<target state="signed-off">使用从开始绕标推断的开始时间</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="controlTrackingFromStartAndFinishTimes" resname="controlTrackingFromStartAndFinishTimes">
|
||||
<source>Control tracking from start and finish times</source>
|
||||
<target>从开始和结束时间控制跟踪</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="numberOfQueueMessagesSent" resname="numberOfQueueMessagesSent">
|
||||
<source>Number of queue messages sent</source>
|
||||
<target state="signed-off">发送的队列消息的数量</target>
|
||||
@@ -4616,8 +4633,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mediaSelectVideoCaption" resname="mediaSelectVideoCaption">
|
||||
<source><ph id="1">{0}</ph> Videos</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>个视频</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>个视频</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mediaSelectVideoTooltip" resname="mediaSelectVideoTooltip">
|
||||
<source>Click to select video</source>
|
||||
@@ -4785,7 +4801,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="noOverallEventSelected" resname="noOverallEventSelected">
|
||||
<source>No overall event selected...</source>
|
||||
<target state="translated">未选择整个活动...</target>
|
||||
<target state="signed-off">未选择整个活动...</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="errorTryingToCreateNewEvent" resname="errorTryingToCreateNewEvent">
|
||||
<source>Error trying to create new event <ph id="1">{0}</ph>: <ph id="2">{1}</ph></source>
|
||||
@@ -5289,8 +5305,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="startingIn" resname="startingIn">
|
||||
<source><ph id="1">{0}</ph> starts in</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>开始于</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>开始于</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="raceIsPlanned" resname="raceIsPlanned">
|
||||
<source>Planned</source>
|
||||
@@ -5322,8 +5337,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="competitorWonRace" resname="competitorWonRace">
|
||||
<source><ph id="1">{0}</ph> won race</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>赢得比赛轮次</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>赢得比赛轮次</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="showCompetitorTimeOnTimeFactorColumn" resname="showCompetitorTimeOnTimeFactorColumn">
|
||||
<source>Time on Time Factor</source>
|
||||
@@ -5467,7 +5481,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="millionValue" resname="millionValue">
|
||||
<source>{0,number,#0.0} mil</source>
|
||||
<target state="translated">{0,number,#0.0} 百万</target>
|
||||
<target state="signed-off">{0,number,#0.0} 百万</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="billionValue" resname="billionValue">
|
||||
<source>{0,number,#0.0} bil</source>
|
||||
@@ -5495,13 +5509,11 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="minutesAgo" resname="minutesAgo">
|
||||
<source><ph id="1">{0}</ph> min ago</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>分钟前</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>分钟前</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="hoursAgo" resname="hoursAgo">
|
||||
<source><ph id="1">{0}</ph> h ago</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>小时前</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>小时前</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="winner" resname="winner">
|
||||
<source>Winner</source>
|
||||
@@ -5537,8 +5549,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="degreesToWind" resname="degreesToWind">
|
||||
<source><ph id="1">{0}</ph>° to wind</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>°(相对于风)</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>°(相对于风)</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="miniLeeaderboardLegendText" resname="miniLeeaderboardLegendText">
|
||||
<source>Shows the points along with the number of races per competitor</source>
|
||||
@@ -5626,8 +5637,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventsHaveTakenPlace" resname="eventsHaveTakenPlace">
|
||||
<source><ph id="1">{0}</ph> events have taken place</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>个活动已举行</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>个活动已举行</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventsHaveTakenPlace[one]" resname="eventsHaveTakenPlace[one]">
|
||||
<source>One event has taken place</source>
|
||||
@@ -5807,8 +5817,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="imageSizeError" resname="imageSizeError">
|
||||
<source>The size of the <ph id="1">{0}</ph> image does not fit. The width should be between <ph id="2">{1}</ph> and <ph id="3">{2}</ph> px and the height between <ph id="4">{3}</ph> and <ph id="5">{4}</ph> px.</source>
|
||||
<target state="signed-off">
|
||||
<ph id="1">{0}</ph>的图像大小不合适。 宽度应在<ph id="2">{1}</ph>和<ph id="3">{2}</ph> px 之间,高度在<ph id="4">{3}</ph>和<ph id="5">{4}</ph> px 之间。</target>
|
||||
<target state="signed-off"><ph id="1">{0}</ph>的图像大小不合适。 宽度应在<ph id="2">{1}</ph>和<ph id="3">{2}</ph> px 之间,高度在<ph id="4">{3}</ph>和<ph id="5">{4}</ph> px 之间。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="couldNotRetrieveImageSizeYet" resname="couldNotRetrieveImageSizeYet">
|
||||
<source>The width and height of the image could not be retrieved yet.</source>
|
||||
@@ -6030,25 +6039,25 @@
|
||||
<source>utm_source=sapsailing&utm_medium=solutions&utm_content=2016.02&utm_campaign=solutions&pcampaignid=2016.sapsailing.solutions</source>
|
||||
<target state="signed-off">utm_source=sapsailing&utm_medium=solutions&utm_content=2016.02&utm_campaign=solutions&pcampaignid=2016.sapsailing.solutions</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreTrackingApp" resname="playstoreTrackingApp">
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreInsightApp" resname="playstoreInsightApp">
|
||||
<source>https://play.google.com/store/apps/details?id=com.sap.sailing.android.tracking.app</source>
|
||||
<target state="signed-off">https://play.google.com/store/apps/details?id=com.sap.sailing.android.tracking.app</target>
|
||||
<target>https://play.google.com/store/apps/details?id=com.sap.sailing.android.tracking.app</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreRacecommitteeApp" resname="playstoreRacecommitteeApp">
|
||||
<source>https://play.google.com/store/apps/details?id=com.sap.sailing.racecommittee.app</source>
|
||||
<target state="signed-off">https://play.google.com/store/apps/details?id=com.sap.sailing.racecommittee.app</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playStoreBuoypositioningApp" resname="playStoreBuoypositioningApp">
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playStoreBuoyPingerApp" resname="playStoreBuoyPingerApp">
|
||||
<source>https://play.google.com/store/apps/details?id=com.sap.sailing.android.buoy.positioning.app</source>
|
||||
<target state="signed-off">https://play.google.com/store/apps/details?id=com.sap.sailing.android.buoy.positioning.app</target>
|
||||
<target>https://play.google.com/store/apps/details?id=com.sap.sailing.android.buoy.positioning.app</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="playstoreBadge" resname="playstoreBadge">
|
||||
<source>https://play.google.com/intl/en/badges/images/generic/en-play-badge.png</source>
|
||||
<target state="signed-off">https://play.google.com/intl/en/badges/images/generic/en-play-badge.png</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="appstoreSapSailingInsight" resname="appstoreSapSailingInsight">
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="appstoreSapSailInsight" resname="appstoreSapSailInsight">
|
||||
<source>http://appstore.com/sapsailinsight</source>
|
||||
<target state="signed-off">http://appstore.com/sapsailinsight</target>
|
||||
<target>http://appstore.com/sapsailinsight</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="appstoreStgTrainingstagebuch" resname="appstoreStgTrainingstagebuch">
|
||||
<source>http://appstore.com/stgtrainingstagebuch</source>
|
||||
@@ -6446,6 +6455,390 @@
|
||||
<source>Maximum number of discards</source>
|
||||
<target state="signed-off">最大放弃次数</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="notificationRegattaConfigurationUpdatedUsingByMarks" resname="notificationRegattaConfigurationUpdatedUsingByMarks">
|
||||
<source>Active regatta configuration was set, using the "By Marks" course designer.</source>
|
||||
<target state="signed-off">已使用“按标志”场地设计器设置有效的比赛配置。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="warningOverrideRegattaConfigurationCourseDesignerToByMarks" resname="warningOverrideRegattaConfigurationCourseDesignerToByMarks">
|
||||
<source>Active regatta configuration already exists, but with the wrong course designer setting.\nWould you like to override course designer setting to "By Marks"?</source>
|
||||
<target state="signed-off">有效的比赛配置已存在,但是场地设计器设置错误。\n是否将场地设计器设置覆盖为“按标志”?</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="allRacesHaveBeenDenoted" resname="allRacesHaveBeenDenoted">
|
||||
<source>All races have been denoted for racelog tracking.</source>
|
||||
<target state="signed-off">已为比赛轮次日志跟踪描述所有比赛轮次。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="chartSelectionHint" resname="chartSelectionHint">
|
||||
<source>Hint: You can also use the leaderboard (on the LEADERBOARD tab) to select the competitors displayed in the chart. </source>
|
||||
<target>提示:您还可以使用积分榜(在 LEADERBOARD 选项卡中)选择在记录中显示的参赛队。 </target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="chooseALanguage" resname="chooseALanguage">
|
||||
<source>Choose a language</source>
|
||||
<target>选择一种语言</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutions" resname="solutions">
|
||||
<source>Solutions</source>
|
||||
<target>解决方案</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="blog" resname="blog">
|
||||
<source>Blog</source>
|
||||
<target>博客</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="officalEventWebsite" resname="officalEventWebsite">
|
||||
<source>Official event website</source>
|
||||
<target>官方活动网站</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="moreInfo" resname="moreInfo">
|
||||
<source>More info</source>
|
||||
<target>更多信息</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="viewAnalysis" resname="viewAnalysis">
|
||||
<source>View analysis </source>
|
||||
<target>查看分析 </target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="overallLeaderboard" resname="overallLeaderboard">
|
||||
<source>Overall leaderboard</source>
|
||||
<target>总积分榜</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="pleaseTryAgain" resname="pleaseTryAgain">
|
||||
<source>Please try again...</source>
|
||||
<target>请重试...</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="reloadPage" resname="reloadPage">
|
||||
<source>Reload page</source>
|
||||
<target>重新加载页面</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="errorMessageLoadingData" resname="errorMessageLoadingData">
|
||||
<source>An error occured while loading the data for this page.</source>
|
||||
<target>加载此页面数据时出错。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="regattaDetails" resname="regattaDetails">
|
||||
<source>Regatta details</source>
|
||||
<target>比赛详情</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="chooseChartType" resname="chooseChartType">
|
||||
<source>Choose chart type</source>
|
||||
<target>选择记录类型</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="whatsNew" resname="whatsNew">
|
||||
<source>What''s new</source>
|
||||
<target>最新消息</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailing" resname="sapSailing">
|
||||
<source>SAP Sailing</source>
|
||||
<target>SAP Sailing</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="search" resname="search">
|
||||
<source>Search</source>
|
||||
<target>搜索</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownStartingInDays" resname="countdownStartingInDays">
|
||||
<source>Days</source>
|
||||
<target>天</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownDays" resname="countdownDays">
|
||||
<source>Days</source>
|
||||
<target>天</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownHours" resname="countdownHours">
|
||||
<source>Hrs</source>
|
||||
<target>小时</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownMinutes" resname="countdownMinutes">
|
||||
<source>Min</source>
|
||||
<target>分钟</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownSeconds" resname="countdownSeconds">
|
||||
<source>Sec</source>
|
||||
<target>秒</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownDay" resname="countdownDay">
|
||||
<source>Day</source>
|
||||
<target>天</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownHour" resname="countdownHour">
|
||||
<source>Hour</source>
|
||||
<target>小时</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownMinute" resname="countdownMinute">
|
||||
<source>Min</source>
|
||||
<target>分钟</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="countdownSecond" resname="countdownSecond">
|
||||
<source>Sec</source>
|
||||
<target>秒</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="liveCapitalLetter" resname="liveCapitalLetter">
|
||||
<source>Live</source>
|
||||
<target>实时</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="watchNow" resname="watchNow">
|
||||
<source>Watch now</source>
|
||||
<target>现在观看</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="seriesHeaderUpcoming" resname="seriesHeaderUpcoming">
|
||||
<source>Upcoming</source>
|
||||
<target>即将到来</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventRegattaLeaderboardLastScoreUpdate" resname="eventRegattaLeaderboardLastScoreUpdate">
|
||||
<source>Last Score Update</source>
|
||||
<target>上次得分更新</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="eventRegattaRaceNotTracked" resname="eventRegattaRaceNotTracked">
|
||||
<source>Not Tracked</source>
|
||||
<target>未跟踪</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerJobs" resname="footerJobs">
|
||||
<source>Jobs</source>
|
||||
<target>招贤纳士</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerCopyright" resname="footerCopyright">
|
||||
<source>© 2011-2016 SAP Sailing Analytics</source>
|
||||
<target>版权所有 © 2011-2016 SAP Sailing Analytics</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerLanguage" resname="footerLanguage">
|
||||
<source>SAP Sailing in</source>
|
||||
<target>SAP Sailing 语言</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerLegal" resname="footerLegal">
|
||||
<source>Legal Disclosure</source>
|
||||
<target>法律声明</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerPrivacy" resname="footerPrivacy">
|
||||
<source>Privacy</source>
|
||||
<target>隐私</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="footerFeedback" resname="footerFeedback">
|
||||
<source>Feedback</source>
|
||||
<target>反馈</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="headerLogo" resname="headerLogo">
|
||||
<source>Sailing Analytics</source>
|
||||
<target>Sailing Analytics</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="headerSearchPlaceholder" resname="headerSearchPlaceholder">
|
||||
<source>Search </source>
|
||||
<target>搜索 </target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainEventShowAll" resname="mainEventShowAll">
|
||||
<source>Show All Events</source>
|
||||
<target>显示所有活动</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainEventTitle" resname="mainEventTitle">
|
||||
<source>Latest Events from the Sailing World</source>
|
||||
<target>来自风帆世界的最新活动</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaSubtitle" resname="mainMediaSubtitle">
|
||||
<source>Get lost in the latest and most beautiful impressions from your favorite sailing event.</source>
|
||||
<target>徜徉在让人着迷、震撼人心的最新航行活动中。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaTitle" resname="mainMediaTitle">
|
||||
<source>Photographers love Sailing</source>
|
||||
<target>摄影师酷爱航行</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaVideosSubtitle" resname="mainMediaVideosSubtitle">
|
||||
<source>Immerse yourself in the world of sailing and check out our latest events for more videos.</source>
|
||||
<target>沉浸在风帆世界中,并通过更多视频了解最新活动。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="mainMediaVideosTitle" resname="mainMediaVideosTitle">
|
||||
<source>Recent Video Entries</source>
|
||||
<target>最近视频条目</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultHeaderButton" resname="searchResultHeaderButton">
|
||||
<source>Search</source>
|
||||
<target>搜索</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultHeaderLabel" resname="searchResultHeaderLabel">
|
||||
<source>Your Search</source>
|
||||
<target>您的搜索</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultHeaderPlaceholder" resname="searchResultHeaderPlaceholder">
|
||||
<source>Type in your searchkey</source>
|
||||
<target>输入搜索关键字</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="searchResultSortNewest" resname="searchResultSortNewest">
|
||||
<source>Recent</source>
|
||||
<target>最近</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsSISHeadline" resname="solutionsSISHeadline">
|
||||
<source>SAP in Sailing</source>
|
||||
<target>SAP in Sailing</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsSAPHeadline" resname="solutionsSAPHeadline">
|
||||
<source>SAP Sailing Analytics</source>
|
||||
<target>SAP Sailing Analytics</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsRaceHeadline" resname="solutionsRaceHeadline">
|
||||
<source>SAP Sailing Race Manager</source>
|
||||
<target>SAP Sailing Race Manager</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsInSightHeadline" resname="solutionsInSightHeadline">
|
||||
<source>SAP Sail InSight</source>
|
||||
<target>SAP Sail InSight</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsBuoyPingerHeadline" resname="solutionsBuoyPingerHeadline">
|
||||
<source>SAP Sailing Buoy Pinger</source>
|
||||
<target>SAP Sailing Buoy Pinger</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsPostHeadline" resname="solutionsPostHeadline">
|
||||
<source>Post-Race Analytics</source>
|
||||
<target>赛后分析</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsTrainingHeadline" resname="solutionsTrainingHeadline">
|
||||
<source>Training Diary</source>
|
||||
<target>训练日记</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="solutionsSimulatorHeadline" resname="solutionsSimulatorHeadline">
|
||||
<source>Strategy Simulator</source>
|
||||
<target>策略模拟器</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapInSailing" resname="sapInSailing">
|
||||
<source>SAP in Sailing</source>
|
||||
<target>SAP in Sailing</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing1" resname="contentSapInSailing1">
|
||||
<source>Sailing provides the perfect platform for SAP to showcase solutions and help the sport run like never before. SAP’s involvement in the sport has transformed the sailing experience by providing tools, which:</source>
|
||||
<target>SAP 凭借此航行应用提供完美的平台,向用户展示解决方案,并以前所未有的顺畅速度呈现体育赛事。 SAP 通过提供各种工具转换其在参与此项运动中获得的航行经验,这些工具:</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing2" resname="contentSapInSailing2">
|
||||
<source>Help sailors analyze performance and optimize strategy</source>
|
||||
<target>帮助水手分析表现并优化策略</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing3" resname="contentSapInSailing3">
|
||||
<source>Bring fans closer to the action</source>
|
||||
<target>让粉丝近距离直击运动</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing4" resname="contentSapInSailing4">
|
||||
<source>Provide the media with information and insights to deliver a greater informed commentary</source>
|
||||
<target>为媒体提供信息和见解,从而提供深度评论</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing5" resname="contentSapInSailing5">
|
||||
<source>SAP has a longstanding involvement with sailing and has established a portfolio spanning across teams and regattas, including:</source>
|
||||
<target>SAP 长期参与航行运动,并成立了跨越团队和比赛的组合,包括:</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing6" resname="contentSapInSailing6">
|
||||
<source>Official Technology Partner of Travemünder Woche</source>
|
||||
<target>特拉沃明德周的官方技术合作伙伴</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing7" resname="contentSapInSailing7">
|
||||
<source>Technical Partner of the European Sailing Leagues</source>
|
||||
<target>欧洲帆船联盟的技术合作伙伴</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing8" resname="contentSapInSailing8">
|
||||
<source>Title sponsor of the SAP Extreme Sailing Team</source>
|
||||
<target>SAP 极限帆船队的冠名赞助商</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing9" resname="contentSapInSailing9">
|
||||
<source>Official Technical Partner of the Extreme Sailing Series</source>
|
||||
<target>极限帆船系列赛的官方技术合作伙伴</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing10" resname="contentSapInSailing10">
|
||||
<source>Premium Partner of Germany’s national sailing team, Audi Sailing Team Germany</source>
|
||||
<target>德国国家帆船队 - 德国奥迪帆船队的优选合作伙伴</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing11" resname="contentSapInSailing11">
|
||||
<source>Premium Partner of the world’s largest regatta, Kieler Woche (Kiel Week)</source>
|
||||
<target>世界上最大的帆船盛事“基尔周”的优选合作伙伴</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapInSailing12" resname="contentSapInSailing12">
|
||||
<source>Title sponsor of the SAP 5O5 World Championships</source>
|
||||
<target>SAP 5O5 世界锦标赛的冠名赞助商</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingAnalyticsTitle" resname="sapSailingAnalyticsTitle">
|
||||
<source>SAP Sailing Analytics</source>
|
||||
<target>SAP Sailing Analytics</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingAnalytics1" resname="contentSapSailingAnalytics1">
|
||||
<source>By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing.</source>
|
||||
<target>通过实时分析比赛轮次排名、速度、操作和航向角等,SAP 可简化此复杂的航行运动,使其浅显易懂。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingAnalytics2" resname="contentSapSailingAnalytics2">
|
||||
<source>SAP Sailing Analytics provide insights and transparency to the world of sailing by utilizing Cloud and In-Memory Technology, processing GPS and wind measurement data in real time and visualizing contents in various frontends accessible from anywhere.</source>
|
||||
<target>SAP Sailing Analytics 利用云和内存技术实时处理 GPS 和风力测量数据,并在可从任何地方访问的前端显示,让用户全面、透彻地了解航行运动。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingAnalyticsReadMore" resname="sapSailingAnalyticsReadMore">
|
||||
<source>Read More</source>
|
||||
<target>更多信息</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingRaceManager" resname="sapSailingRaceManager">
|
||||
<source>SAP Sailing Race Manager</source>
|
||||
<target>SAP Sailing Race Manager</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingRaceManager" resname="contentSapSailingRaceManager">
|
||||
<source>The SAP Sailing Race Manager delivers greater efficiency and control to race organizers by automating and simplifying their manual tasks and communication during running sailing regattas. The Race Committee App helps simplify the operation of running and managing race events to help race committees operate smarter.</source>
|
||||
<target>SAP Sailing Race Manager 通过自动化及简化赛事主办机构在航行比赛期间的人工作业和沟通,实现更高的效率和控制能力。Race Committee 应用简化举办和管理比赛活动的操作,使竞赛委员会的操作更加智能。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingRaceManagerReadMore" resname="sapSailingRaceManagerReadMore">
|
||||
<source>Learn More</source>
|
||||
<target>了解更多</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailInSight" resname="sapSailInSight">
|
||||
<source>SAP Sail InSight</source>
|
||||
<target>SAP Sail InSight</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailInSight" resname="contentSapSailInSight">
|
||||
<source>With the SAP Sail InSight mobile app for iPhone, iPad and Android phones, sailboat racers can manage their regatta participation and performance anywhere and anytime. This app connects to the SAP Sailing Analytics solution and enables racers to sign in to an SAP Sail InSight-enabled regatta, track their location together with performance indicators like speed or distance sailed, and analyze their performance.</source>
|
||||
<target>使用适用于 iPhone、iPad 和 Android 手机的 SAP Sail InSight 移动应用,帆船选手可以随时随地管理其参赛情况和表现。此应用与 SAP Sailing Analytics 解决方案相连,选手可以登录启用 SAP Sail InSight 的比赛,跟踪其所处地点和速度或航行距离等表现指标,并分析其表现。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailInSightReadMore" resname="sapSailInSightReadMore">
|
||||
<source>Learn More</source>
|
||||
<target>了解更多</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingBuoyPinger" resname="sapSailingBuoyPinger">
|
||||
<source>SAP Sailing Buoy Pinger</source>
|
||||
<target>SAP Sailing Buoy Pinger</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentSapSailingBuoyPinger" resname="contentSapSailingBuoyPinger">
|
||||
<source>With the SAP Sailing Buoy Pinger mobile app for Android phones, sailboat race managers can simplify the positioning of race marks and communication with the mark layers anywhere and anytime. This app connects to the SAP Sailing Analytics solution and allows regatta managers to track the geographical position of their race marks, enabling the use of the SAP Sail InSight mobile app by sailors participating in the regatta.</source>
|
||||
<target>使用适用于 Android 手机的 SAP Sailing Buoy Pinger 移动应用,帆船赛赛事经理可以随时随地简化比赛航标的定位和与布标裁判的沟通。此应用与 SAP Sailing Analytics 解决方案相连,比赛经理可以跟踪其比赛航标的地理位置,并允许参赛水手使用 SAP Sail InSight 移动应用。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="sapSailingBuoyPingerReadMore" resname="sapSailingBuoyPingerReadMore">
|
||||
<source>Learn More</source>
|
||||
<target>了解更多</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="postRaceAnalytics" resname="postRaceAnalytics">
|
||||
<source>Post-Race Analytics</source>
|
||||
<target>赛后分析</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentPostRaceAnalytics1" resname="contentPostRaceAnalytics1">
|
||||
<source>Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better.</source>
|
||||
<target>水手通过访问航行活动期间收集的数据评估和分析其表现,帮助他们制定策略和优化航行方案。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentPostRaceAnalytics2" resname="contentPostRaceAnalytics2">
|
||||
<source>SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas.</source>
|
||||
<target>SAP Business Analytics 解决方案为水手、教练、粉丝和媒体提供跨比赛和轮次浏览和分析历史数据的工具。SAP HANA 通过简单、快速和高效的方式使其了解表现模式、趋势和水手资料,从而提高自己的表现并为今后的比赛制定成功的策略。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="i18nDeSolutionsTrainingHeadline" resname="i18nDeSolutionsTrainingHeadline">
|
||||
<source>SAP Sail Better – STG Training Diary</source>
|
||||
<target>SAP Sail Better – STG Training Diary</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="i18nDeSolutionsTrainingText" resname="i18nDeSolutionsTrainingText">
|
||||
<source>The STG Training Diary supports the daily documentation and analysis of an athlete’s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel.</source>
|
||||
<target>STG Training Diary 可每天记录和分析运动员的身体状况,在水上训练、体能训练、船艇工作、心理、理论以及教育或旅行等其他活动领域的训练力度。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="strategySimulator" resname="strategySimulator">
|
||||
<source>Strategy Simulator</source>
|
||||
<target>策略模拟器</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="contentStrategySimulator" resname="contentStrategySimulator">
|
||||
<source>Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions.</source>
|
||||
<target>选择正确的策略可在比赛期间极大地提高竞争优势。策略模拟器为不同的风力条件和水流简化确定最佳的航行策略。由于可以在模拟中即时更改风和水流,即便在不确定的天气条件下,也可以轻松地评估策略的稳健性。</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="strategySimulatorReadMore" resname="strategySimulatorReadMore">
|
||||
<source>Learn More</source>
|
||||
<target>了解更多</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="impressum" resname="impressum">
|
||||
<source>Imprint</source>
|
||||
<target>版本说明</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="lastFix" resname="lastFix">
|
||||
<source>Last fix</source>
|
||||
<target>上次修复</target>
|
||||
</trans-unit>
|
||||
<trans-unit datatype="x-urn:x-sap:sls-mlt:java:flexible-converter:messageformat" id="filterDeviceMappings" resname="filterDeviceMappings">
|
||||
<source>Filter device mappings</source>
|
||||
<target>筛选设备映射</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
@@ -1,146 +1,148 @@
|
||||
# Welcome to the SAP Sailing Wiki
|
||||
|
||||
This is the <img src="https://www.sapsailing.com/images/sap-logo_grey.png"/> Wiki where useful information regarding this project can be found.
|
||||
|
||||
### The Pitch
|
||||
|
||||
Like businesses, sailors need the latest information to make strategic decisions - but they need it even faster. One wrong tack, a false estimation of the current, or the slightest wind shift can cost the skipper the entire race. As premium sponsor of the Kieler Woche 2011, and co-sponsor of Sailing Team Germany (STG), SAP is showing how innovative IT solutions providing real time data analysis can give teams the competitive edge.
|
||||
|
||||
SAP is at the center of today’s technology revolution, developing innovations that not only help businesses run like never before, but also improve the lives of people everywhere. As market leader in enterprise application software, SAP SE (NYSE: SAP) helps companies of all sizes and industries run better. From back office to boardroom, warehouse to storefront, desktop to mobile device – SAP empowers people and organizations to work together more efficiently and use business insight more effectively to stay ahead of the competition. SAP applications and services enable more than 258,000 customers to operate profitably, adapt continuously, and grow sustainably.
|
||||
|
||||
# Table of Contents
|
||||
|
||||
## Information
|
||||
|
||||
### General
|
||||
|
||||
* [[Information about this Wiki and HowTo|wiki/info/general/wiki]]
|
||||
* [[General Project Information|wiki/info/general/general-information]]
|
||||
* [[Inventory|wiki/info/general/inventar-liste]]
|
||||
|
||||
### Landscape and Development
|
||||
|
||||
* [[Architecture and Infrastructure|wiki/info/landscape/architecture-and-infrastructure]]
|
||||
* [[Runtime Environment|wiki/info/landscape/runtime-environment]]
|
||||
* [[Basic architectual principles|wiki/info/landscape/basic-architectural-principles]]
|
||||
* [[User Management|wiki/info/landscape/usermanagement]]
|
||||
* [[Development Environment|wiki/info/landscape/development-environment]]
|
||||
* [[Production Environment|wiki/info/landscape/production-environment]]
|
||||
* [[Typical Development Scenarios|wiki/info/landscape/typical-development-scenarios]]
|
||||
* [[RaceLog Tracking Server Architecture|wiki/info/landscape/server]]
|
||||
* Environment Overview [[PDF|wiki/info/mobile/event-tracking/architecture.pdf]] | [[SVG|wiki/info/mobile/event-tracking/architecture.svg]]
|
||||
* Amazon
|
||||
* [[Amazon EC2|wiki/info/landscape/amazon-ec2]]
|
||||
* [[EC2 Backup Strategy|wiki/info/landscape/amazon-ec2-backup-strategy]]
|
||||
* [[Creating an EC2 image from scratch|wiki/info/landscape/creating-ec2-image-from-scratch]]
|
||||
* [[EC2 mail relaying|wiki/info/landscape/mail-relaying]]
|
||||
* [[Building and Deploying|wiki/info/landscape/building-and-deploying]]
|
||||
* [[Data Mining Architecture|wiki/info/landscape/data-mining-architecture]]
|
||||
* [[Typical Data Mining Scenarios|wiki/info/landscape/typical-data-mining-scenarios]]
|
||||
* [[Create clickable UI prototypes with Axure|wiki/info/landscape/ui-clickable-prototypes]]
|
||||
* [[Webdesign|wiki/info/landscape/webdesign]]
|
||||
|
||||
### Mobile
|
||||
|
||||
* [[Mobile Development|wiki/info/mobile/mobile-development]]
|
||||
* Tracking App
|
||||
* [[Tracking App Specification|wiki/info/mobile/app-spec/app-spec]]
|
||||
* [[Event Tracking|wiki/info/mobile/event-tracking/event-tracking]]
|
||||
* [[Steps for setting up Smartphone Tracking|wiki/info/mobile/smartphone-tracking-steps]]
|
||||
* [[Tracking App Prototype Architecture|wiki/info/mobile/app]]
|
||||
* Racecommittee App
|
||||
* [[Racecommittee App|wiki/info/mobile/racecommittee-app]]
|
||||
* [[Environment|wiki/info/mobile/racecommittee-app-environment]]
|
||||
* [[Administrator|wiki/info/mobile/racecommittee-app-administrator]]
|
||||
* [[User|wiki/info/mobile/racecommittee-app-user]]
|
||||
* [[Android and Release Build|wiki/info/mobile/android-and-release-build]]
|
||||
* [[Mobile Sailing Analytics|wiki/info/mobile/mobilesailinganalytics]]
|
||||
* [[Push Notifications|wiki/info/mobile/push-notifications]]
|
||||
|
||||
### API
|
||||
|
||||
* [[Web Services API|wiki/info/api/sailing-webservices]]
|
||||
* [[API v1|wiki/info/api/api-v1]]
|
||||
* [[Tracking App API|wiki/info/api/tracking-app-api]]
|
||||
* [[Training API v1 draft|wiki/info/api/training-api-v1-draft]]
|
||||
|
||||
### Security
|
||||
* [[Fortify Tests|wiki/info/security/fortify]]
|
||||
* [[SSL / HTTPS Support|wiki/info/security/ssl-support]]
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
* [[Big Data - Numbers|wiki/info/misc/big-data-numbers]]
|
||||
* [[Data Quality|wiki/info/misc/data-quality]]
|
||||
* [[Sailing Domain Algorithms|wiki/info/misc/sailing-domain-algorithms]]
|
||||
* [[Google Analytics (Web Page Tracking)|wiki/info/misc/ganalytics]]
|
||||
* [[S3 Development Sample|wiki/info/misc/s3-sample]]
|
||||
|
||||
* [[FAQ for League Operators|wiki/info/misc/league-operators-faq]]
|
||||
* [[Prionet related information|wiki/info/misc/prionet-related-information]]
|
||||
* [[TracTrac Workshop 2013|wiki/info/misc/tractracworkshop2013]]
|
||||
|
||||
## HowTo
|
||||
|
||||
* [[Onboarding|wiki/howto/onboarding]]
|
||||
|
||||
|
||||
### Development
|
||||
|
||||
* [[Create boat graphics for the 2D race viewer|wiki/howto/development/boatgraphicssvg]]
|
||||
* [[Continuous Integration with Hudson/Jenkins|wiki/howto/development/ci]]
|
||||
* [[Dispatch|wiki/howto/development/dispatch]]
|
||||
* [[Working with GWT UI Binder|wiki/howto/development/gwt-ui-binder]]
|
||||
* [[Java De(Serialization) and Circular Dependencies|wiki/howto/development/java-de-serialization-and-circular-dependencies]]
|
||||
* [[JMX Support|wiki/howto/development/jmx]]
|
||||
* [[Working with GWT Locally|wiki/howto/development/local-gwt]]
|
||||
* [[Log File Analysis|wiki/howto/development/log-file-analysis]]
|
||||
* [[UI Tests with Selenium|wiki/howto/development/selenium-ui-tests]]
|
||||
* [[Profiling|wiki/howto/development/profiling]]
|
||||
* [[Working with GWT Super Dev Mode|wiki/howto/development/super-dev-mode]]
|
||||
|
||||
### For Event Managers
|
||||
|
||||
* [[Set up local network with replication server|wiki/howto/eventmanagers/event-network-with-replica]]
|
||||
* [[Operating Igtimi WindBots|wiki/howto/eventmanagers/windbot-operations]]
|
||||
* [[Linking Race Videos|wiki/howto/eventmanagers/linking-race-videos]]
|
||||
* [[Import official results|wiki/howto/eventmanagers/results-import]]
|
||||
|
||||
### Setup
|
||||
|
||||
* [[Configure Races on Server|wiki/howto/setup/configure-races-on-server]]
|
||||
* [[Setting up internal Jenkins on SAP Monsoon|wiki/howto/setup/setting-up-jenkins-on-sap-monsoon]]
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
* [[Cook Book|wiki/howto/misc/cook-book]]
|
||||
* [[Polars|wiki/howto/misc/polars]]
|
||||
* [[Server Replication|wiki/howto/misc/server-replication]]
|
||||
* [[TracTrac|wiki/howto/misc/tractrac-lifecycle]]
|
||||
* [[UI Tests|wiki/howto/misc/ui-tests-tutorial]]
|
||||
* [[Uploading Media Content|wiki/howto/misc/uploading-media-content]]
|
||||
* [[Monitoring Apache and RabbitMQ|wiki/misc/monitoring-apache-and-rabbitmq]]
|
||||
|
||||
## Projects
|
||||
* [[Analytics on a stick|wiki/projects/analytics-on-a-stick]]
|
||||
|
||||
## Events and Planning
|
||||
* [[Project Planning (bigger development)|wiki/events/planning]]
|
||||
* [[General Event Planning|wiki/events/general-event-planning]]
|
||||
* [[Information about Extreme Sailing Series|wiki/events/extreme-sailing-series]]
|
||||
* [[Travemünder Woche 2014 event page|wiki/events/tw2014]]
|
||||
* [[505 worlds Kiel 2014 event page|wiki/events/505-worlds-kiel-2014]]
|
||||
* [[Kieler Woche event page|wiki/events/kieler-woche-2015]]
|
||||
* [[Charleston Race Week 2016|wiki/events/Charleston-Race-Week-2016]]
|
||||
* [[Sailing Leagues 2016|wiki/events/sailing-Leagues-2016]]
|
||||
|
||||
## Planning
|
||||
* [[Overview|https://wiki.sapsailing.com/pages/wiki/planning/]]
|
||||
|
||||
## Internal services (not related to wiki but useful)
|
||||
|
||||
* [Bugzilla Issue Tracking System](http://bugzilla.sapsailing.com/bugzilla/)
|
||||
* [GIT Repository (SAP)](ssh://git.wdf.sap.corp:29418/SAPSail/sapsailingcapture.git)
|
||||
* [Maven Repository Browser](http://maven.sapsailing.com/maven/) (see [[how to setup repository for Android builds|wiki/info/mobile/racecommittee-app-environment]])
|
||||
* [Main Sailing Website](http://www.sapsailing.com)
|
||||
* [Visitor Statistics](http://analysis.sapsailing.com/)
|
||||
# Welcome to the SAP Sailing Wiki
|
||||
|
||||
This is the <img src="https://www.sapsailing.com/images/sap-logo_grey.png"/> Wiki where useful information regarding this project can be found.
|
||||
|
||||
### The Pitch
|
||||
|
||||
Like businesses, sailors need the latest information to make strategic decisions - but they need it even faster. One wrong tack, a false estimation of the current, or the slightest wind shift can cost the skipper the entire race. As premium sponsor of the Kieler Woche 2011, and co-sponsor of Sailing Team Germany (STG), SAP is showing how innovative IT solutions providing real time data analysis can give teams the competitive edge.
|
||||
|
||||
SAP is at the center of today’s technology revolution, developing innovations that not only help businesses run like never before, but also improve the lives of people everywhere. As market leader in enterprise application software, SAP SE (NYSE: SAP) helps companies of all sizes and industries run better. From back office to boardroom, warehouse to storefront, desktop to mobile device – SAP empowers people and organizations to work together more efficiently and use business insight more effectively to stay ahead of the competition. SAP applications and services enable more than 258,000 customers to operate profitably, adapt continuously, and grow sustainably.
|
||||
|
||||
# Table of Contents
|
||||
|
||||
## Information
|
||||
|
||||
### General
|
||||
|
||||
* [[Information about this Wiki and HowTo|wiki/info/general/wiki]]
|
||||
* [[General Project Information|wiki/info/general/general-information]]
|
||||
* [[Inventory|wiki/info/general/inventar-liste]]
|
||||
|
||||
### Landscape and Development
|
||||
|
||||
* [[Architecture and Infrastructure|wiki/info/landscape/architecture-and-infrastructure]]
|
||||
* [[Runtime Environment|wiki/info/landscape/runtime-environment]]
|
||||
* [[Basic architectual principles|wiki/info/landscape/basic-architectural-principles]]
|
||||
* [[User Management|wiki/info/landscape/usermanagement]]
|
||||
* [[Development Environment|wiki/info/landscape/development-environment]]
|
||||
* [[Production Environment|wiki/info/landscape/production-environment]]
|
||||
* [[Typical Development Scenarios|wiki/info/landscape/typical-development-scenarios]]
|
||||
* [[RaceLog Tracking Server Architecture|wiki/info/landscape/server]]
|
||||
* Environment Overview [[PDF|wiki/info/mobile/event-tracking/architecture.pdf]] | [[SVG|wiki/info/mobile/event-tracking/architecture.svg]]
|
||||
* Amazon
|
||||
* [[Amazon EC2|wiki/info/landscape/amazon-ec2]]
|
||||
* [[EC2 Backup Strategy|wiki/info/landscape/amazon-ec2-backup-strategy]]
|
||||
* [[Creating an EC2 image from scratch|wiki/info/landscape/creating-ec2-image-from-scratch]]
|
||||
* [[EC2 mail relaying|wiki/info/landscape/mail-relaying]]
|
||||
* [[Building and Deploying|wiki/info/landscape/building-and-deploying]]
|
||||
* [[Data Mining Architecture|wiki/info/landscape/data-mining-architecture]]
|
||||
* [[Typical Data Mining Scenarios|wiki/info/landscape/typical-data-mining-scenarios]]
|
||||
* [[Create clickable UI prototypes with Axure|wiki/info/landscape/ui-clickable-prototypes]]
|
||||
* [[Webdesign|wiki/info/landscape/webdesign]]
|
||||
|
||||
### Mobile
|
||||
|
||||
* [[Mobile Development|wiki/info/mobile/mobile-development]]
|
||||
* Tracking App
|
||||
* [[Tracking App Specification|wiki/info/mobile/app-spec/app-spec]]
|
||||
* [[Event Tracking|wiki/info/mobile/event-tracking/event-tracking]]
|
||||
* [[Steps for setting up Smartphone Tracking|wiki/info/mobile/smartphone-tracking-steps]]
|
||||
* [[Tracking App Prototype Architecture|wiki/info/mobile/app]]
|
||||
* Racecommittee App
|
||||
* [[Racecommittee App|wiki/info/mobile/racecommittee-app]]
|
||||
* [[Environment|wiki/info/mobile/racecommittee-app-environment]]
|
||||
* [[Administrator|wiki/info/mobile/racecommittee-app-administrator]]
|
||||
* [[User|wiki/info/mobile/racecommittee-app-user]]
|
||||
* [[Android and Release Build|wiki/info/mobile/android-and-release-build]]
|
||||
* [[Energy consumption of mobile apps|wiki/info/mobile/energy-consumption]]
|
||||
* [[Data consumption of mobile apps|wiki/info/mobile/data-consumption]]
|
||||
* [[Mobile Sailing Analytics|wiki/info/mobile/mobilesailinganalytics]]
|
||||
* [[Push Notifications|wiki/info/mobile/push-notifications]]
|
||||
|
||||
### API
|
||||
|
||||
* [[Web Services API|wiki/info/api/sailing-webservices]]
|
||||
* [[API v1|wiki/info/api/api-v1]]
|
||||
* [[Tracking App API|wiki/info/api/tracking-app-api]]
|
||||
* [[Training API v1 draft|wiki/info/api/training-api-v1-draft]]
|
||||
|
||||
### Security
|
||||
* [[Fortify Tests|wiki/info/security/fortify]]
|
||||
* [[SSL / HTTPS Support|wiki/info/security/ssl-support]]
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
* [[Big Data - Numbers|wiki/info/misc/big-data-numbers]]
|
||||
* [[Data Quality|wiki/info/misc/data-quality]]
|
||||
* [[Sailing Domain Algorithms|wiki/info/misc/sailing-domain-algorithms]]
|
||||
* [[Google Analytics (Web Page Tracking)|wiki/info/misc/ganalytics]]
|
||||
* [[S3 Development Sample|wiki/info/misc/s3-sample]]
|
||||
|
||||
* [[FAQ for League Operators|wiki/info/misc/league-operators-faq]]
|
||||
* [[Prionet related information|wiki/info/misc/prionet-related-information]]
|
||||
* [[TracTrac Workshop 2013|wiki/info/misc/tractracworkshop2013]]
|
||||
|
||||
## HowTo
|
||||
|
||||
* [[Onboarding|wiki/howto/onboarding]]
|
||||
|
||||
|
||||
### Development
|
||||
|
||||
* [[Create boat graphics for the 2D race viewer|wiki/howto/development/boatgraphicssvg]]
|
||||
* [[Continuous Integration with Hudson/Jenkins|wiki/howto/development/ci]]
|
||||
* [[Dispatch|wiki/howto/development/dispatch]]
|
||||
* [[Working with GWT UI Binder|wiki/howto/development/gwt-ui-binder]]
|
||||
* [[Java De(Serialization) and Circular Dependencies|wiki/howto/development/java-de-serialization-and-circular-dependencies]]
|
||||
* [[JMX Support|wiki/howto/development/jmx]]
|
||||
* [[Working with GWT Locally|wiki/howto/development/local-gwt]]
|
||||
* [[Log File Analysis|wiki/howto/development/log-file-analysis]]
|
||||
* [[UI Tests with Selenium|wiki/howto/development/selenium-ui-tests]]
|
||||
* [[Profiling|wiki/howto/development/profiling]]
|
||||
* [[Working with GWT Super Dev Mode|wiki/howto/development/super-dev-mode]]
|
||||
|
||||
### For Event Managers
|
||||
|
||||
* [[Set up local network with replication server|wiki/howto/eventmanagers/event-network-with-replica]]
|
||||
* [[Operating Igtimi WindBots|wiki/howto/eventmanagers/windbot-operations]]
|
||||
* [[Linking Race Videos|wiki/howto/eventmanagers/linking-race-videos]]
|
||||
* [[Import official results|wiki/howto/eventmanagers/results-import]]
|
||||
|
||||
### Setup
|
||||
|
||||
* [[Configure Races on Server|wiki/howto/setup/configure-races-on-server]]
|
||||
* [[Setting up internal Jenkins on SAP Monsoon|wiki/howto/setup/setting-up-jenkins-on-sap-monsoon]]
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
* [[Cook Book|wiki/howto/misc/cook-book]]
|
||||
* [[Polars|wiki/howto/misc/polars]]
|
||||
* [[Server Replication|wiki/howto/misc/server-replication]]
|
||||
* [[TracTrac|wiki/howto/misc/tractrac-lifecycle]]
|
||||
* [[UI Tests|wiki/howto/misc/ui-tests-tutorial]]
|
||||
* [[Uploading Media Content|wiki/howto/misc/uploading-media-content]]
|
||||
* [[Monitoring Apache and RabbitMQ|wiki/misc/monitoring-apache-and-rabbitmq]]
|
||||
|
||||
## Projects
|
||||
* [[Analytics on a stick|wiki/projects/analytics-on-a-stick]]
|
||||
|
||||
## Events and Planning
|
||||
* [[Project Planning (bigger development)|wiki/events/planning]]
|
||||
* [[General Event Planning|wiki/events/general-event-planning]]
|
||||
* [[Information about Extreme Sailing Series|wiki/events/extreme-sailing-series]]
|
||||
* [[Travemünder Woche 2014 event page|wiki/events/tw2014]]
|
||||
* [[505 worlds Kiel 2014 event page|wiki/events/505-worlds-kiel-2014]]
|
||||
* [[Kieler Woche event page|wiki/events/kieler-woche-2015]]
|
||||
* [[Charleston Race Week 2016|wiki/events/Charleston-Race-Week-2016]]
|
||||
* [[Sailing Leagues 2016|wiki/events/sailing-Leagues-2016]]
|
||||
|
||||
## Planning
|
||||
* [[Overview|https://wiki.sapsailing.com/pages/wiki/planning/]]
|
||||
|
||||
## Internal services (not related to wiki but useful)
|
||||
|
||||
* [Bugzilla Issue Tracking System](http://bugzilla.sapsailing.com/bugzilla/)
|
||||
* [GIT Repository (SAP)](ssh://git.wdf.sap.corp:29418/SAPSail/sapsailingcapture.git)
|
||||
* [Maven Repository Browser](http://maven.sapsailing.com/maven/) (see [[how to setup repository for Android builds|wiki/info/mobile/racecommittee-app-environment]])
|
||||
* [Main Sailing Website](http://www.sapsailing.com)
|
||||
* [Visitor Statistics](http://analysis.sapsailing.com/)
|
||||
Binary file not shown.
+1
-1
@@ -161,7 +161,7 @@ public class StartAnalysisCard extends Composite implements HasWidgets, StartAna
|
||||
final RaceMapSettings raceMapSettings = new RaceMapSettings(raceMapZoomSettings, getHelpLineSettings(),
|
||||
defaultRaceMapSettings.getTransparentHoverlines(), defaultRaceMapSettings.getHoverlineStrokeWeight(),
|
||||
startAnalysisDTO.tailLenghtInMilliseconds, defaultRaceMapSettings.isWindUp(),
|
||||
defaultRaceMapSettings.getBuoyZoneRadiusInMeters(), defaultRaceMapSettings.isShowOnlySelectedCompetitors(),
|
||||
defaultRaceMapSettings.getBuoyZoneRadius(), defaultRaceMapSettings.isShowOnlySelectedCompetitors(),
|
||||
defaultRaceMapSettings.isShowSelectedCompetitorsInfo(), defaultRaceMapSettings.isShowWindStreamletColors(),
|
||||
defaultRaceMapSettings.isShowWindStreamletOverlay(), defaultRaceMapSettings.isShowSimulationOverlay(),
|
||||
defaultRaceMapSettings.isShowMapControls(), defaultRaceMapSettings.getManeuverTypesToShow(),
|
||||
|
||||
+6
@@ -2,6 +2,9 @@ package com.sap.sailing.datamining.shared;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.LegType;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.NauticalSide;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.common.impl.CentralAngleDistance;
|
||||
import com.sap.sailing.domain.common.impl.MeterDistance;
|
||||
import com.sap.sailing.domain.common.impl.NauticalMileDistance;
|
||||
@@ -16,6 +19,9 @@ public final class SailingDataMiningSerializationDummy implements SerializationD
|
||||
private CentralAngleDistance centralAngleDistance;
|
||||
private MeterDistance meterDistance;
|
||||
private NauticalMileDistance nauticalMileDistance;
|
||||
private ManeuverType maneuverType;
|
||||
private Tack tack;
|
||||
private NauticalSide nauticalSide;
|
||||
|
||||
private SailingDataMiningSerializationDummy() { }
|
||||
|
||||
|
||||
+22
-6
@@ -16,6 +16,7 @@ Race=Race
|
||||
Competitor=Competitor
|
||||
Boat=Boat
|
||||
Team=Team
|
||||
CompetitorSearchTag=Competitor Search Tag
|
||||
LeaderboardSailingDomainRetrieverChain=Leaderboards
|
||||
RaceSailingDomainRetrieverChain=Races
|
||||
LegSailingDomainRetrieverChain=Legs
|
||||
@@ -23,12 +24,14 @@ GPSFixSailingDomainRetrieverChain=GPS-Fixes
|
||||
MarkPassingSailingDomainRetrieverChain=Mark Passings
|
||||
RaceResultSailingDomainRetrieverChain=Race Results
|
||||
RaceOfCompetitorSailingDomainRetrieverChain=Races of Competitors
|
||||
ManeuverSailingDomainRetrieverChain=Maneuver
|
||||
LeaderboardGroup=Leaderboard Group
|
||||
Leaderboard=Leaderboard
|
||||
Leg=Leg
|
||||
MarkPassing=Mark Passing
|
||||
LegOfCompetitor=Leg of competitor
|
||||
GpsFix=GPS-Fix
|
||||
Maneuver=Maneuver
|
||||
WindStrengthInBeaufort=Wind Strength in Beaufort
|
||||
Bft0=Calm
|
||||
Bft1=Light air
|
||||
@@ -43,11 +46,12 @@ Bft9=Strong gale
|
||||
Bft10=Storm
|
||||
Bft11=Violent storm
|
||||
Bft12=Hurricane
|
||||
RelativeScoreInRace=Relative score in race (0 best; 1 worst)
|
||||
WindSpeedInBeaufort=Wind speed in Bft
|
||||
DistanceAtStart=Distance to start at start
|
||||
SpeedWhenStarting=Speed when starting
|
||||
SpeedTenSecondsBeforeStart=Speed 10s before start
|
||||
RelativeScore=Relative Score (0 best; 1 worst)
|
||||
AbsoluteRank=Absolute Rank
|
||||
WindSpeedInBeaufort=Wind Speed in Bft
|
||||
DistanceAtStart=Distance to Start at Start
|
||||
SpeedWhenStarting=Speed at Start
|
||||
SpeedTenSecondsBeforeStart=Speed 10s Before Start
|
||||
RankAtFirstMark=Rank at First Mark
|
||||
NumberOfManeuvers=Number of Maneuvers
|
||||
NumberOfTacks=Number of Tacks
|
||||
@@ -60,4 +64,16 @@ NumberOfWins=Number of Wins
|
||||
RankGainsOrLossesBetweenFirstMarkAndFinish=Rank Gains or Losses (1st Mark -> Finish)
|
||||
IsTracked=Is Tracked
|
||||
NumberOfCompetitorFixes=Number of Competitor Fixes
|
||||
NumberOfMarkFixes=Number of Mark Fixes
|
||||
NumberOfMarkFixes=Number of Mark Fixes
|
||||
ManeuverType=Maneuver Type
|
||||
Tack=Tack
|
||||
SpeedBefore=Speed Before Maneuver
|
||||
SpeedAfter=Speed After Maneuver
|
||||
DirectionChange=Direction Change in Degrees
|
||||
ManeuverLoss=Maneuver Loss
|
||||
Waypoint=Waypoint
|
||||
PassingSide=Passing Side
|
||||
TackAtStart=Tack at Start
|
||||
SpeedTenSecondsAfterStart=Speed 10s After Start
|
||||
RankThirtySecondsAfterStart=Rank 30s After Start
|
||||
StartAdvantage=Start Advantage
|
||||
+18
-2
@@ -3,6 +3,7 @@ DistanceTraveled=zur
|
||||
Boat=Boot
|
||||
Team=Team
|
||||
Name=Name
|
||||
CompetitorSearchTag=Teilnehmer Such-Tag
|
||||
Nationality=Nationalitäts
|
||||
Acronym=Abkürzung
|
||||
SailID=Segelnummer
|
||||
@@ -21,12 +22,14 @@ GPSFixSailingDomainRetrieverChain=GPS-Fixes
|
||||
MarkPassingSailingDomainRetrieverChain=Tonnenrundungen
|
||||
RaceResultSailingDomainRetrieverChain=Rennergebnisse
|
||||
RaceOfCompetitorSailingDomainRetrieverChain=Rennen eines Teilnehmers
|
||||
ManeuverSailingDomainRetrieverChain=Manöver
|
||||
LeaderboardGroup=Ranglisten Gruppe
|
||||
Leaderboard=Rangliste
|
||||
Leg=Schenkel
|
||||
MarkPassing=Tonnenrundung
|
||||
LegOfCompetitor=Schenkel eines Teilnehmers
|
||||
GpsFix=GPS-Fix
|
||||
Maneuver=Manöver
|
||||
Speed=Geschwindigkeit
|
||||
SpeedTenSecondsBefore=Geschwindigkeit 10s vorher
|
||||
WindStrengthInBeaufort=Windstärke in Beaufort
|
||||
@@ -43,7 +46,8 @@ Bft9=Sturm
|
||||
Bft10=schwerer Sturm
|
||||
Bft11=orkanartiger Sturm
|
||||
Bft12=Orkan
|
||||
RelativeScoreInRace=Relative Wertung im Rennen (0 am besten; 1 am schlechtesten)
|
||||
RelativeScore=Relative Wertung (0 am besten; 1 am schlechtesten)
|
||||
AbsoluteRank=Absolute Platzierung
|
||||
WindSpeedInBeaufort=Windgeschwindigkeit in Bft.
|
||||
DistanceAtStart=Distanz zur Startlinie zum Startzeitpunkt
|
||||
SpeedWhenStarting=Geschwindigkeit beim Überqueren der Startlinie
|
||||
@@ -60,4 +64,16 @@ NumberOfWins=Anzahl der Siege
|
||||
RankGainsOrLossesBetweenFirstMarkAndFinish=Positions-Verluste oder -Gewinne (1ter Wegpunkt -> Ziel)
|
||||
IsTracked=Ist getracked
|
||||
NumberOfCompetitorFixes=Anzahl der Teilnehmer-Fixes
|
||||
NumberOfMarkFixes=Anzahl der Tonnen-Fixes
|
||||
NumberOfMarkFixes=Anzahl der Tonnen-Fixes
|
||||
ManeuverType=Art des Manövers
|
||||
Tack=Bug
|
||||
SpeedBefore=Geschwindigkeit bevor dem Manöver
|
||||
SpeedAfter=Geschwindigkeit nach dem Manöver
|
||||
DirectionChange=Richtungsänderung in Grad
|
||||
ManeuverLoss=Manöververlust
|
||||
Waypoint=Wegpunkt
|
||||
PassingSide=Passierende Seite
|
||||
TackAtStart=Startbug
|
||||
SpeedTenSecondsAfterStart=Geschwindigkeit 10s nach dem Startzeitpunkt
|
||||
RankThirtySecondsAfterStart=Absolute Platzierung 30s nach dem Startzeitpunkt
|
||||
StartAdvantage=Startvorteil
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file datatype="javapropertyresourcebundle" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages.properties" source-language="en">
|
||||
<file datatype="javapropertyresourcebundle" original="/usr/sap/ljs/app/Converter_6482944262098570487/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages.properties" source-language="en">
|
||||
<header>
|
||||
<skl>
|
||||
<internal-file crc="2476e2fa472ba5cb7a43d465af58c5c7" form="base64">H4sIAAAAAAAAAIVVTW8aMRC9+1fMpVJyiATptypXAiIIFfkQoEY9mt0BLBYb2SaU/vrO2Muuk0b04p1582zPjO23sx1iKWc8ijjO0cywsKb0fVxahykG3Y6HRQTEjfZBmQLnTj1jRbNPAJwQca+2KHkQE1zNjzuU9AU2xEzpanwj+QP3++0CnfiFykkemJ2wyK/D9ypoa1Slw1FmtugVzprjVtZfMcWVCkHJ+isGdu889hwqmUxgW/StCoNKeS/ZgmiKYYUYZBzFVBUoeaAVtjsMOlgnWzMuEOeKOaqt5IESVyW6hVWu5Mq0Wd3YrdJmisFpfEY3WJMnM5qP+5wjc9xzS86vuPJi9Dgb6t/naMS4Igqtd6fc5pFKJua5CUyDmpdSnaLfV+F/CUOipSkPy7Zt/60U7BJaus9bOnJ2v8ubBxHJKXmUe8aNyWt9URAT8tzibaPti/aQRztP/Tr1TTxpU86CQ7MK67Hpo9rTUwiSYTjhoA2cIqK/DB05UNWWra6c6NU6gNKO3evaXTjEP8jIezlCEyrMoA/yzlJBKuTgRzl06NcZ8knS9tasMuizvKXl4UC5sftFjlQVA19P3FUNdDuEWJdy7Mqf2laUBvgGu5a3e+d0oQzS86ro8T3jrCARGJv0SmoMPIPcAMd34KJDWuHDN+jCgY4yXKb+sZC8bp6P6sKdW4ZGWXphFhQxGmEJlpIiBFRIRtKqpzWJFbt8wEmnDgQlCp/zm4qW1n4ta/W6U2U2vTDUlDXfGMk+7xoRYEgkWXpY3lFX9nSHvUwI36AGa1hzVWxyRvSb6A9Njcqi0W+ij0hSF44D7YrqBa0OQB2JWY/oJfkHN7HeEzfmHSGwDhLYKrflHiS10uWb7W4IwAy4eMfbTuI9v2zzs6Xeb4faaL/Os4swJDwrhw48L4LdfzPvYzggmuYEeqasN3irJLjo1scCV9/rHS/F2NOfqNjQr2nsoTabLNpnHwUxS6iNQNLK9qTd5jU57plofwGIogiCRAcAAA==</internal-file>
|
||||
</skl>
|
||||
<phase-group>
|
||||
<phase company-name="SAP AG" date="2016-05-11T12:28:06Z" phase-name="file-creation" process-name="file-creation" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter"/>
|
||||
<phase company-name="SAP AG" date="2016-09-23T09:24:36Z" phase-name="file-creation" process-name="file-creation" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter"/>
|
||||
</phase-group>
|
||||
<tool tool-company="SAP AG" tool-id="urn:x-sap:sls-mlt:java:properties-flexible-converter" tool-name="TEW: Javascript .properties Flexible File Converter" tool-version="1.1.0"/>
|
||||
</header>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-08-12T10:45:09Z" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages.properties" source-language="en" target-language="ja">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-09-29T12:16:25Z" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages.properties" source-language="en" target-language="ja">
|
||||
<header>
|
||||
<skl>
|
||||
<internal-file crc="2476e2fa472ba5cb7a43d465af58c5c7" form="base64">H4sIAAAAAAAAAIVVTW8aMRC9+1fMpVJyiATptypXAiIIFfkQoEY9mt0BLBYb2SaU/vrO2Muuk0b04p1582zPjO23sx1iKWc8ijjO0cywsKb0fVxahykG3Y6HRQTEjfZBmQLnTj1jRbNPAJwQca+2KHkQE1zNjzuU9AU2xEzpanwj+QP3++0CnfiFykkemJ2wyK/D9ypoa1Slw1FmtugVzprjVtZfMcWVCkHJ+isGdu889hwqmUxgW/StCoNKeS/ZgmiKYYUYZBzFVBUoeaAVtjsMOlgnWzMuEOeKOaqt5IESVyW6hVWu5Mq0Wd3YrdJmisFpfEY3WJMnM5qP+5wjc9xzS86vuPJi9Dgb6t/naMS4Igqtd6fc5pFKJua5CUyDmpdSnaLfV+F/CUOipSkPy7Zt/60U7BJaus9bOnJ2v8ubBxHJKXmUe8aNyWt9URAT8tzibaPti/aQRztP/Tr1TTxpU86CQ7MK67Hpo9rTUwiSYTjhoA2cIqK/DB05UNWWra6c6NU6gNKO3evaXTjEP8jIezlCEyrMoA/yzlJBKuTgRzl06NcZ8knS9tasMuizvKXl4UC5sftFjlQVA19P3FUNdDuEWJdy7Mqf2laUBvgGu5a3e+d0oQzS86ro8T3jrCARGJv0SmoMPIPcAMd34KJDWuHDN+jCgY4yXKb+sZC8bp6P6sKdW4ZGWXphFhQxGmEJlpIiBFRIRtKqpzWJFbt8wEmnDgQlCp/zm4qW1n4ta/W6U2U2vTDUlDXfGMk+7xoRYEgkWXpY3lFX9nSHvUwI36AGa1hzVWxyRvSb6A9Njcqi0W+ij0hSF44D7YrqBa0OQB2JWY/oJfkHN7HeEzfmHSGwDhLYKrflHiS10uWb7W4IwAy4eMfbTuI9v2zzs6Xeb4faaL/Os4swJDwrhw48L4LdfzPvYzggmuYEeqasN3irJLjo1scCV9/rHS/F2NOfqNjQr2nsoTabLNpnHwUxS6iNQNLK9qTd5jU57plofwGIogiCRAcAAA==</internal-file>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-08-12T11:06:51Z" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages.properties" source-language="en" target-language="ru">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-09-29T12:16:25Z" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages.properties" source-language="en" target-language="ru">
|
||||
<header>
|
||||
<skl>
|
||||
<internal-file crc="2476e2fa472ba5cb7a43d465af58c5c7" form="base64">H4sIAAAAAAAAAIVVTW8aMRC9+1fMpVJyiATptypXAiIIFfkQoEY9mt0BLBYb2SaU/vrO2Muuk0b04p1582zPjO23sx1iKWc8ijjO0cywsKb0fVxahykG3Y6HRQTEjfZBmQLnTj1jRbNPAJwQca+2KHkQE1zNjzuU9AU2xEzpanwj+QP3++0CnfiFykkemJ2wyK/D9ypoa1Slw1FmtugVzprjVtZfMcWVCkHJ+isGdu889hwqmUxgW/StCoNKeS/ZgmiKYYUYZBzFVBUoeaAVtjsMOlgnWzMuEOeKOaqt5IESVyW6hVWu5Mq0Wd3YrdJmisFpfEY3WJMnM5qP+5wjc9xzS86vuPJi9Dgb6t/naMS4Igqtd6fc5pFKJua5CUyDmpdSnaLfV+F/CUOipSkPy7Zt/60U7BJaus9bOnJ2v8ubBxHJKXmUe8aNyWt9URAT8tzibaPti/aQRztP/Tr1TTxpU86CQ7MK67Hpo9rTUwiSYTjhoA2cIqK/DB05UNWWra6c6NU6gNKO3evaXTjEP8jIezlCEyrMoA/yzlJBKuTgRzl06NcZ8knS9tasMuizvKXl4UC5sftFjlQVA19P3FUNdDuEWJdy7Mqf2laUBvgGu5a3e+d0oQzS86ro8T3jrCARGJv0SmoMPIPcAMd34KJDWuHDN+jCgY4yXKb+sZC8bp6P6sKdW4ZGWXphFhQxGmEJlpIiBFRIRtKqpzWJFbt8wEmnDgQlCp/zm4qW1n4ta/W6U2U2vTDUlDXfGMk+7xoRYEgkWXpY3lFX9nSHvUwI36AGa1hzVWxyRvSb6A9Njcqi0W+ij0hSF44D7YrqBa0OQB2JWY/oJfkHN7HeEzfmHSGwDhLYKrflHiS10uWb7W4IwAy4eMfbTuI9v2zzs6Xeb4faaL/Os4swJDwrhw48L4LdfzPvYzggmuYEeqasN3irJLjo1scCV9/rHS/F2NOfqNjQr2nsoTabLNpnHwUxS6iNQNLK9qTd5jU57plofwGIogiCRAcAAA==</internal-file>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-08-12T11:06:52Z" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages.properties" source-language="en" target-language="zh-CN">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-09-29T12:16:25Z" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.datamining/resources/stringmessages/Sailing_StringMessages.properties" source-language="en" target-language="zh-CN">
|
||||
<header>
|
||||
<skl>
|
||||
<internal-file crc="2476e2fa472ba5cb7a43d465af58c5c7" form="base64">H4sIAAAAAAAAAIVVTW8aMRC9+1fMpVJyiATptypXAiIIFfkQoEY9mt0BLBYb2SaU/vrO2Muuk0b04p1582zPjO23sx1iKWc8ijjO0cywsKb0fVxahykG3Y6HRQTEjfZBmQLnTj1jRbNPAJwQca+2KHkQE1zNjzuU9AU2xEzpanwj+QP3++0CnfiFykkemJ2wyK/D9ypoa1Slw1FmtugVzprjVtZfMcWVCkHJ+isGdu889hwqmUxgW/StCoNKeS/ZgmiKYYUYZBzFVBUoeaAVtjsMOlgnWzMuEOeKOaqt5IESVyW6hVWu5Mq0Wd3YrdJmisFpfEY3WJMnM5qP+5wjc9xzS86vuPJi9Dgb6t/naMS4Igqtd6fc5pFKJua5CUyDmpdSnaLfV+F/CUOipSkPy7Zt/60U7BJaus9bOnJ2v8ubBxHJKXmUe8aNyWt9URAT8tzibaPti/aQRztP/Tr1TTxpU86CQ7MK67Hpo9rTUwiSYTjhoA2cIqK/DB05UNWWra6c6NU6gNKO3evaXTjEP8jIezlCEyrMoA/yzlJBKuTgRzl06NcZ8knS9tasMuizvKXl4UC5sftFjlQVA19P3FUNdDuEWJdy7Mqf2laUBvgGu5a3e+d0oQzS86ro8T3jrCARGJv0SmoMPIPcAMd34KJDWuHDN+jCgY4yXKb+sZC8bp6P6sKdW4ZGWXphFhQxGmEJlpIiBFRIRtKqpzWJFbt8wEmnDgQlCp/zm4qW1n4ta/W6U2U2vTDUlDXfGMk+7xoRYEgkWXpY3lFX9nSHvUwI36AGa1hzVWxyRvSb6A9Njcqi0W+ij0hSF44D7YrqBa0OQB2JWY/oJfkHN7HeEzfmHSGwDhLYKrflHiS10uWb7W4IwAy4eMfbTuI9v2zzs6Xeb4faaL/Os4swJDwrhw48L4LdfzPvYzggmuYEeqasN3irJLjo1scCV9/rHS/F2NOfqNjQr2nsoTabLNpnHwUxS6iNQNLK9qTd5jU57plofwGIogiCRAcAAA==</internal-file>
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.osgi.framework.BundleContext;
|
||||
import com.sap.sailing.datamining.data.HasGPSFixContext;
|
||||
import com.sap.sailing.datamining.data.HasLeaderboardContext;
|
||||
import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
|
||||
import com.sap.sailing.datamining.data.HasManeuverContext;
|
||||
import com.sap.sailing.datamining.data.HasMarkPassingContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
|
||||
@@ -82,6 +83,7 @@ public class Activator extends AbstractDataMiningActivatorWithPredefinedQueries
|
||||
internalClasses.add(HasTrackedLegContext.class);
|
||||
internalClasses.add(HasTrackedLegOfCompetitorContext.class);
|
||||
internalClasses.add(HasGPSFixContext.class);
|
||||
internalClasses.add(HasManeuverContext.class);
|
||||
internalClasses.add(HasMarkPassingContext.class);
|
||||
internalClasses.add(HasRaceOfCompetitorContext.class);
|
||||
internalClasses.add(HasLeaderboardGroupContext.class);
|
||||
|
||||
+13
-5
@@ -5,6 +5,7 @@ import java.util.Collection;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasGPSFixContext;
|
||||
import com.sap.sailing.datamining.data.HasLeaderboardContext;
|
||||
import com.sap.sailing.datamining.data.HasManeuverContext;
|
||||
import com.sap.sailing.datamining.data.HasMarkPassingContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
|
||||
@@ -15,6 +16,7 @@ import com.sap.sailing.datamining.impl.components.CompetitorOfRaceInLeaderboardR
|
||||
import com.sap.sailing.datamining.impl.components.GPSFixRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.LeaderboardGroupRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.LeaderboardRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.ManeuverRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.MarkPassingRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.RaceOfCompetitorRetrievalProcessor;
|
||||
import com.sap.sailing.datamining.impl.components.TrackedLegOfCompetitorRetrievalProcessor;
|
||||
@@ -48,11 +50,6 @@ public class SailingDataRetrievalChainDefinitions {
|
||||
trackedRaceRetrieverChainDefinition.endWith(LeaderboardRetrievalProcessor.class, TrackedRaceRetrievalProcessor.class,
|
||||
HasTrackedRaceContext.class, "Race");
|
||||
dataRetrieverChainDefinitions.add(trackedRaceRetrieverChainDefinition);
|
||||
|
||||
final DataRetrieverChainDefinition<RacingEventService, HasMarkPassingContext> markPassingRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
|
||||
trackedRaceRetrieverChainDefinition, HasMarkPassingContext.class, "MarkPassingSailingDomainRetrieverChain");
|
||||
markPassingRetrieverChainDefinition.endWith(TrackedRaceRetrievalProcessor.class, MarkPassingRetrievalProcessor.class, HasMarkPassingContext.class, "MarkPassing");
|
||||
dataRetrieverChainDefinitions.add(markPassingRetrieverChainDefinition);
|
||||
|
||||
final DataRetrieverChainDefinition<RacingEventService, HasRaceOfCompetitorContext> raceOfCompetitorRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
|
||||
trackedRaceRetrieverChainDefinition, HasRaceOfCompetitorContext.class, "RaceOfCompetitorSailingDomainRetrieverChain");
|
||||
@@ -71,6 +68,17 @@ public class SailingDataRetrievalChainDefinitions {
|
||||
gpsFixRetrieverChainDefinition.endWith(TrackedLegOfCompetitorRetrievalProcessor.class, GPSFixRetrievalProcessor.class,
|
||||
HasGPSFixContext.class, "GpsFix");
|
||||
dataRetrieverChainDefinitions.add(gpsFixRetrieverChainDefinition);
|
||||
|
||||
final DataRetrieverChainDefinition<RacingEventService, HasManeuverContext> maneuverRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
|
||||
legOfCompetitorRetrieverChainDefinition, HasManeuverContext.class, "ManeuverSailingDomainRetrieverChain");
|
||||
maneuverRetrieverChainDefinition.endWith(TrackedLegOfCompetitorRetrievalProcessor.class, ManeuverRetrievalProcessor.class,
|
||||
HasManeuverContext.class, "Maneuver");
|
||||
dataRetrieverChainDefinitions.add(maneuverRetrieverChainDefinition);
|
||||
|
||||
final DataRetrieverChainDefinition<RacingEventService, HasMarkPassingContext> markPassingRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
|
||||
legOfCompetitorRetrieverChainDefinition, HasMarkPassingContext.class, "MarkPassingSailingDomainRetrieverChain");
|
||||
markPassingRetrieverChainDefinition.endWith(TrackedLegOfCompetitorRetrievalProcessor.class, MarkPassingRetrievalProcessor.class, HasMarkPassingContext.class, "MarkPassing");
|
||||
dataRetrieverChainDefinitions.add(markPassingRetrieverChainDefinition);
|
||||
}
|
||||
|
||||
public Iterable<DataRetrieverChainDefinition<?, ?>> get() {
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.sap.sailing.datamining.data;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sse.datamining.annotations.Connector;
|
||||
import com.sap.sse.datamining.annotations.Dimension;
|
||||
import com.sap.sse.datamining.annotations.Statistic;
|
||||
|
||||
public interface HasManeuverContext {
|
||||
|
||||
@Connector(scanForStatistics=false)
|
||||
HasTrackedLegOfCompetitorContext getTrackedLegOfCompetitorContext();
|
||||
|
||||
Maneuver getManeuver();
|
||||
|
||||
//TODO Clean-Up:
|
||||
// Move Dimensions and Statistics to Maneuver and connect to it
|
||||
@Dimension(messageKey="ManeuverType", ordinal=12)
|
||||
ManeuverType getManeuverType();
|
||||
|
||||
@Dimension(messageKey="Tack", ordinal=13)
|
||||
Tack getTack();
|
||||
|
||||
@Connector(messageKey="SpeedBefore", ordinal=0)
|
||||
SpeedWithBearing getSpeedBefore();
|
||||
@Connector(messageKey="SpeedAfter", ordinal=1)
|
||||
SpeedWithBearing getSpeedAfter();
|
||||
|
||||
@Statistic(messageKey="DirectionChange", resultDecimals=2, ordinal=2)
|
||||
Double getDirectionChangeInDegrees();
|
||||
|
||||
@Statistic(messageKey="ManeuverLoss", resultDecimals=0, ordinal=3)
|
||||
Distance getManeuverLoss();
|
||||
|
||||
}
|
||||
+32
-16
@@ -1,29 +1,45 @@
|
||||
package com.sap.sailing.datamining.data;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.NauticalSide;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.tracking.MarkPassingManeuver;
|
||||
import com.sap.sse.datamining.annotations.Connector;
|
||||
import com.sap.sse.datamining.annotations.Dimension;
|
||||
import com.sap.sse.datamining.annotations.Statistic;
|
||||
|
||||
public interface HasMarkPassingContext {
|
||||
|
||||
@Connector
|
||||
HasTrackedRaceContext getTrackedRaceContext();
|
||||
@Connector(scanForStatistics=false)
|
||||
HasTrackedLegOfCompetitorContext getTrackedLegOfCompetitorContext();
|
||||
|
||||
MarkPassingManeuver getManeuver();
|
||||
|
||||
//TODO Clean-Up:
|
||||
// Move Dimensions and Statistics to Maneuver/MarkPassingManeuver and connect to it
|
||||
// Find a way to implement HasManeuverContext and HasMarkPassingManeuver with a base class
|
||||
@Dimension(messageKey="Tack", ordinal=12)
|
||||
Tack getTack();
|
||||
|
||||
@Connector(messageKey="Waypoint", ordinal=13)
|
||||
Waypoint getWaypoint();
|
||||
|
||||
@Dimension(messageKey="PassingSide", ordinal=13)
|
||||
NauticalSide getPassingSide();
|
||||
|
||||
@Connector
|
||||
MarkPassing getMarkPassing();
|
||||
@Connector(messageKey="SpeedBefore", ordinal=0)
|
||||
SpeedWithBearing getSpeedBefore();
|
||||
@Connector(messageKey="SpeedAfter", ordinal=1)
|
||||
SpeedWithBearing getSpeedAfter();
|
||||
|
||||
@Connector(messageKey="Competitor")
|
||||
Competitor getCompetitor();
|
||||
@Statistic(messageKey="DirectionChange", resultDecimals=2, ordinal=2)
|
||||
Double getDirectionChangeInDegrees();
|
||||
|
||||
@Connector(messageKey="Speed", ordinal=1)
|
||||
Speed getSpeed();
|
||||
@Statistic(messageKey="RelativeScore", ordinal=3, resultDecimals=2)
|
||||
Double getRelativeRank();
|
||||
|
||||
@Connector(messageKey="SpeedTenSecondsBefore", ordinal=2)
|
||||
Speed getSpeedTenSecondsBefore();
|
||||
@Statistic(messageKey="AbsoluteRank", ordinal=4, resultDecimals=2)
|
||||
Double getAbsoluteRank();
|
||||
|
||||
@Dimension(messageKey="LegType", ordinal=6)
|
||||
String getPreviousLegTypeSignifier() throws NoWindException;
|
||||
}
|
||||
+32
-14
@@ -2,8 +2,11 @@ package com.sap.sailing.datamining.data;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sse.datamining.annotations.Connector;
|
||||
import com.sap.sse.datamining.annotations.Dimension;
|
||||
import com.sap.sse.datamining.annotations.Statistic;
|
||||
|
||||
public interface HasRaceOfCompetitorContext {
|
||||
@@ -14,34 +17,49 @@ public interface HasRaceOfCompetitorContext {
|
||||
@Connector(messageKey="Competitor")
|
||||
public Competitor getCompetitor();
|
||||
|
||||
@Dimension(messageKey="CompetitorSearchTag", ordinal=11) // TODO Clean me: Move Dimension to Competitor when possible
|
||||
public String getCompetitorSearchTag();
|
||||
|
||||
@Dimension(messageKey="TackAtStart", ordinal=12)
|
||||
public Tack getTackAtStart() throws NoWindException;
|
||||
|
||||
@Statistic(messageKey="DistanceAtStart", resultDecimals=2, ordinal=0)
|
||||
public Distance getDistanceToStartLineAtStart();
|
||||
|
||||
@Statistic(messageKey="DistanceToStarboardSideAtStart", resultDecimals=2, ordinal=1)
|
||||
public Double getNormalizedDistanceToStarboardSideAtStart();
|
||||
|
||||
// @Statistic(messageKey="StartAdvantage", resultDecimals=2, ordinal=2)
|
||||
// public Double getNormalizedDistanceToFavoredEndAtStart();
|
||||
|
||||
@Connector(messageKey="SpeedWhenStarting", ordinal=2)
|
||||
public Speed getSpeedWhenStarting();
|
||||
|
||||
@Connector(messageKey="SpeedTenSecondsBeforeStart", ordinal=3)
|
||||
public Speed getSpeedTenSecondsBeforeStart();
|
||||
|
||||
@Statistic(messageKey="RankAtFirstMark", resultDecimals=2, ordinal=4)
|
||||
@Connector(messageKey="SpeedTenSecondsAfterStart", ordinal=4)
|
||||
public Speed getSpeedTenSecondsAfterStart();
|
||||
|
||||
@Statistic(messageKey="RankThirtySecondsAfterStart", resultDecimals=2, ordinal=5)
|
||||
public Double getAbsoluteRankThirtySecondsAfterStart();
|
||||
|
||||
@Statistic(messageKey="RankAtFirstMark", resultDecimals=2, ordinal=6)
|
||||
public Double getRankAtFirstMark();
|
||||
|
||||
@Statistic(messageKey="NumberOfManeuvers", resultDecimals=0, ordinal=5)
|
||||
public int getNumberOfManeuvers();
|
||||
|
||||
@Statistic(messageKey="NumberOfTacks", resultDecimals=2, ordinal=6)
|
||||
public int getNumberOfTacks();
|
||||
|
||||
@Statistic(messageKey="NumberOfJibes", resultDecimals=2, ordinal=7)
|
||||
public int getNumberOfJibes();
|
||||
|
||||
@Statistic(messageKey="NumberOfPenaltyCircles", resultDecimals=2, ordinal=8)
|
||||
public int getNumberOfPenaltyCircles();
|
||||
|
||||
@Statistic(messageKey="RankGainsOrLossesBetweenFirstMarkAndFinish", resultDecimals=2, ordinal=9)
|
||||
@Statistic(messageKey="RankGainsOrLossesBetweenFirstMarkAndFinish", resultDecimals=2, ordinal=7)
|
||||
public Double getRankGainsOrLossesBetweenFirstMarkAndFinish();
|
||||
|
||||
@Statistic(messageKey="NumberOfManeuvers", resultDecimals=0, ordinal=8)
|
||||
public int getNumberOfManeuvers();
|
||||
|
||||
@Statistic(messageKey="NumberOfTacks", resultDecimals=2, ordinal=9)
|
||||
public int getNumberOfTacks();
|
||||
|
||||
@Statistic(messageKey="NumberOfJibes", resultDecimals=2, ordinal=10)
|
||||
public int getNumberOfJibes();
|
||||
|
||||
@Statistic(messageKey="NumberOfPenaltyCircles", resultDecimals=2, ordinal=11)
|
||||
public int getNumberOfPenaltyCircles();
|
||||
|
||||
}
|
||||
+17
-11
@@ -12,22 +12,28 @@ public interface HasRaceResultOfCompetitorContext {
|
||||
|
||||
@Connector(messageKey="Competitor")
|
||||
public Competitor getCompetitor();
|
||||
|
||||
/**
|
||||
* 0 means the competitor won the race, 1 means the competitor ranked last
|
||||
*/
|
||||
@Statistic(messageKey="RelativeScoreInRace", ordinal=1, resultDecimals=2)
|
||||
public double getRelativeRank();
|
||||
|
||||
@Dimension(messageKey="WindSpeedInBeaufort")
|
||||
int getAverageWindSpeedInRoundedBeaufort();
|
||||
|
||||
@Dimension(messageKey="Regatta")
|
||||
String getRegattaName();
|
||||
|
||||
@Statistic(messageKey="NumberOfPodiumFinish", ordinal=2)
|
||||
@Dimension(messageKey="CompetitorSearchTag", ordinal=11) // TODO Clean me: Move Dimension to Competitor when possible
|
||||
public String getCompetitorSearchTag();
|
||||
|
||||
@Dimension(messageKey="WindSpeedInBeaufort")
|
||||
int getAverageWindSpeedInRoundedBeaufort();
|
||||
|
||||
/**
|
||||
* 0 means the competitor won the race, 1 means the competitor ranked last
|
||||
*/
|
||||
@Statistic(messageKey="RelativeScore", ordinal=1, resultDecimals=2)
|
||||
public Double getRelativeRank();
|
||||
|
||||
@Statistic(messageKey="AbsoluteRank", ordinal=2, resultDecimals=2)
|
||||
public Double getAbsoluteRank();
|
||||
|
||||
@Statistic(messageKey="NumberOfPodiumFinish", ordinal=3)
|
||||
public Boolean isPodiumFinish();
|
||||
|
||||
@Statistic(messageKey="NumberOfWins", ordinal=3)
|
||||
@Statistic(messageKey="NumberOfWins", ordinal=4)
|
||||
public Boolean isWin();
|
||||
}
|
||||
+10
@@ -4,6 +4,7 @@ import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sse.datamining.annotations.Connector;
|
||||
import com.sap.sse.datamining.annotations.Dimension;
|
||||
import com.sap.sse.datamining.annotations.Statistic;
|
||||
|
||||
public interface HasTrackedLegOfCompetitorContext {
|
||||
@@ -12,6 +13,9 @@ public interface HasTrackedLegOfCompetitorContext {
|
||||
public HasTrackedLegContext getTrackedLegContext();
|
||||
|
||||
public TrackedLegOfCompetitor getTrackedLegOfCompetitor();
|
||||
|
||||
@Dimension(messageKey="CompetitorSearchTag", ordinal=11) // TODO Clean me: Move Dimension to Competitor when possible
|
||||
public String getCompetitorSearchTag();
|
||||
|
||||
@Connector(messageKey="Competitor")
|
||||
public Competitor getCompetitor();
|
||||
@@ -21,5 +25,11 @@ public interface HasTrackedLegOfCompetitorContext {
|
||||
|
||||
@Statistic(messageKey="RankGainsOrLosses", resultDecimals=2, ordinal=1)
|
||||
public Double getRankGainsOrLosses();
|
||||
|
||||
@Statistic(messageKey="RelativeScore", resultDecimals=2, ordinal=2)
|
||||
public Double getRelativeRank();
|
||||
|
||||
@Statistic(messageKey="AbsoluteRank", resultDecimals=2, ordinal=3)
|
||||
public Double getAbsoluteRank();
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.sap.sailing.datamining.impl.components;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasManeuverContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.impl.data.ManeuverWithContext;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
|
||||
|
||||
public class ManeuverRetrievalProcessor extends AbstractRetrievalProcessor<HasTrackedLegOfCompetitorContext, HasManeuverContext> {
|
||||
|
||||
public ManeuverRetrievalProcessor(ExecutorService executor, Collection<Processor<HasManeuverContext, ?>> resultReceivers, int retrievalLevel) {
|
||||
super(HasTrackedLegOfCompetitorContext.class, HasManeuverContext.class, executor, resultReceivers, retrievalLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<HasManeuverContext> retrieveData(HasTrackedLegOfCompetitorContext element) {
|
||||
Collection<HasManeuverContext> maneuversWithContext = new ArrayList<>();
|
||||
TimePoint finishTime = element.getTrackedLegOfCompetitor().getFinishTime();
|
||||
if (finishTime != null) {
|
||||
try {
|
||||
List<Maneuver> maneuvers = element.getTrackedLegOfCompetitor().getManeuvers(finishTime, false);
|
||||
for (Maneuver maneuver : maneuvers) {
|
||||
maneuversWithContext.add(new ManeuverWithContext(element, maneuver));
|
||||
}
|
||||
} catch (NoWindException e) {
|
||||
throw new IllegalStateException("No wind retrieving the maneuvers", e);
|
||||
}
|
||||
}
|
||||
return maneuversWithContext;
|
||||
}
|
||||
|
||||
}
|
||||
+23
-24
@@ -1,46 +1,45 @@
|
||||
package com.sap.sailing.datamining.impl.components;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasMarkPassingContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.datamining.impl.data.MarkPassingWithContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.MarkPassingManeuver;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.datamining.components.Processor;
|
||||
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
|
||||
|
||||
public class MarkPassingRetrievalProcessor extends AbstractRetrievalProcessor<HasTrackedRaceContext, HasMarkPassingContext> {
|
||||
public class MarkPassingRetrievalProcessor extends AbstractRetrievalProcessor<HasTrackedLegOfCompetitorContext, HasMarkPassingContext> {
|
||||
|
||||
public MarkPassingRetrievalProcessor(ExecutorService executor,
|
||||
Collection<Processor<HasMarkPassingContext, ?>> resultReceivers, int retrievalLevel) {
|
||||
super(HasTrackedRaceContext.class, HasMarkPassingContext.class, executor, resultReceivers, retrievalLevel);
|
||||
super(HasTrackedLegOfCompetitorContext.class, HasMarkPassingContext.class, executor, resultReceivers, retrievalLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<HasMarkPassingContext> retrieveData(HasTrackedRaceContext element) {
|
||||
TrackedRace trackedRace = element.getTrackedRace();
|
||||
Set<HasMarkPassingContext> result = new HashSet<>();
|
||||
trackedRace.getRace().getCourse().lockForRead();
|
||||
try {
|
||||
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
|
||||
NavigableSet<MarkPassing> markPassingsForCompetitor = trackedRace.getMarkPassings(competitor);
|
||||
trackedRace.lockForRead(markPassingsForCompetitor);
|
||||
try {
|
||||
markPassingsForCompetitor.stream().forEach(mp->result.add(new MarkPassingWithContext(element, mp)));
|
||||
} finally {
|
||||
trackedRace.unlockAfterRead(markPassingsForCompetitor);
|
||||
protected Iterable<HasMarkPassingContext> retrieveData(HasTrackedLegOfCompetitorContext element) {
|
||||
Collection<HasMarkPassingContext> maneuversWithContext = new ArrayList<>();
|
||||
TimePoint finishTime = element.getTrackedLegOfCompetitor().getFinishTime();
|
||||
if (finishTime != null) {
|
||||
try {
|
||||
List<Maneuver> maneuvers = element.getTrackedLegOfCompetitor().getManeuvers(finishTime, false);
|
||||
for (Maneuver maneuver : maneuvers) {
|
||||
if (maneuver.getType() == ManeuverType.MARK_PASSING) {
|
||||
maneuversWithContext.add(new MarkPassingWithContext(element, (MarkPassingManeuver) maneuver));
|
||||
}
|
||||
}
|
||||
} catch (NoWindException e) {
|
||||
throw new IllegalStateException("No wind retrieving the mark passings", e);
|
||||
}
|
||||
} finally {
|
||||
trackedRace.getRace().getCourse().unlockAfterRead();
|
||||
}
|
||||
return result;
|
||||
return maneuversWithContext;
|
||||
}
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package com.sap.sailing.datamining.impl.data;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasManeuverContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
|
||||
public class ManeuverWithContext implements HasManeuverContext {
|
||||
|
||||
private final HasTrackedLegOfCompetitorContext trackedLegOfCompetitor;
|
||||
private final Maneuver maneuver;
|
||||
|
||||
public ManeuverWithContext(HasTrackedLegOfCompetitorContext trackedLegOfCompetitor, Maneuver maneuver) {
|
||||
this.trackedLegOfCompetitor = trackedLegOfCompetitor;
|
||||
this.maneuver = maneuver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HasTrackedLegOfCompetitorContext getTrackedLegOfCompetitorContext() {
|
||||
return trackedLegOfCompetitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maneuver getManeuver() {
|
||||
return maneuver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManeuverType getManeuverType() {
|
||||
return getManeuver().getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tack getTack() {
|
||||
return getManeuver().getNewTack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpeedWithBearing getSpeedBefore() {
|
||||
return getManeuver().getSpeedWithBearingBefore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpeedWithBearing getSpeedAfter() {
|
||||
return getManeuver().getSpeedWithBearingAfter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getDirectionChangeInDegrees() {
|
||||
return getManeuver().getDirectionChangeInDegrees();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getManeuverLoss() {
|
||||
return getManeuver().getManeuverLoss();
|
||||
}
|
||||
|
||||
}
|
||||
+62
-49
@@ -1,74 +1,87 @@
|
||||
package com.sap.sailing.datamining.impl.data;
|
||||
|
||||
import com.sap.sailing.datamining.data.HasMarkPassingContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.common.NauticalSide;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.tracking.MarkPassingManeuver;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class MarkPassingWithContext implements HasMarkPassingContext {
|
||||
private final HasTrackedRaceContext trackedRaceContext;
|
||||
private final MarkPassing markPassing;
|
||||
|
||||
public MarkPassingWithContext(HasTrackedRaceContext trackedRaceContext, MarkPassing markPassing) {
|
||||
super();
|
||||
this.trackedRaceContext = trackedRaceContext;
|
||||
this.markPassing = markPassing;
|
||||
private final HasTrackedLegOfCompetitorContext trackedLegOfCompetitor;
|
||||
private final MarkPassingManeuver maneuver;
|
||||
|
||||
private Double absoluteRank;
|
||||
private boolean rankHasBeenInitialized;
|
||||
|
||||
public MarkPassingWithContext(HasTrackedLegOfCompetitorContext trackedLegOfCompetitor, MarkPassingManeuver maneuver) {
|
||||
this.trackedLegOfCompetitor = trackedLegOfCompetitor;
|
||||
this.maneuver = maneuver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HasTrackedRaceContext getTrackedRaceContext() {
|
||||
return trackedRaceContext;
|
||||
public HasTrackedLegOfCompetitorContext getTrackedLegOfCompetitorContext() {
|
||||
return trackedLegOfCompetitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkPassing getMarkPassing() {
|
||||
return markPassing;
|
||||
public MarkPassingManeuver getManeuver() {
|
||||
return maneuver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Competitor getCompetitor() {
|
||||
return markPassing.getCompetitor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeed() {
|
||||
return getTrackedRace().getTrack(getCompetitor()).getEstimatedSpeed(getMarkPassing().getTimePoint());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeedTenSecondsBefore() {
|
||||
return getTrackedRace().getTrack(getCompetitor()).getEstimatedSpeed(getMarkPassing().getTimePoint().minus(10000 /* ms */));
|
||||
}
|
||||
|
||||
private TrackedRace getTrackedRace() {
|
||||
return trackedRaceContext.getTrackedRace();
|
||||
public Tack getTack() {
|
||||
return getManeuver().getNewTack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreviousLegTypeSignifier() throws NoWindException {
|
||||
final String result;
|
||||
TrackedLeg previousLeg = getPreviousLeg();
|
||||
if (previousLeg == null) {
|
||||
result = "Start";
|
||||
} else {
|
||||
result = previousLeg.getLegType(getMarkPassing().getTimePoint()).toString();
|
||||
}
|
||||
return result;
|
||||
public Waypoint getWaypoint() {
|
||||
return getManeuver().getWaypointPassed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NauticalSide getPassingSide() {
|
||||
return getManeuver().getSide();
|
||||
}
|
||||
|
||||
private TrackedLeg getPreviousLeg() {
|
||||
final TrackedLeg result;
|
||||
Waypoint waypoint = markPassing.getWaypoint();
|
||||
if (waypoint == getTrackedRace().getRace().getCourse().getFirstWaypoint()) {
|
||||
result = null;
|
||||
} else {
|
||||
result = getTrackedRace().getTrackedLegFinishingAt(waypoint);
|
||||
}
|
||||
return result;
|
||||
@Override
|
||||
public SpeedWithBearing getSpeedBefore() {
|
||||
return getManeuver().getSpeedWithBearingBefore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpeedWithBearing getSpeedAfter() {
|
||||
return getManeuver().getSpeedWithBearingAfter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getDirectionChangeInDegrees() {
|
||||
return getManeuver().getDirectionChangeInDegrees();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getRelativeRank() {
|
||||
Leaderboard leaderboard = getTrackedLegOfCompetitorContext().getTrackedLegContext().getTrackedRaceContext().getLeaderboardContext().getLeaderboard();
|
||||
double competitorCount = Util.size(leaderboard.getCompetitors());
|
||||
return getAbsoluteRank() == null ? null : getAbsoluteRank() / competitorCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getAbsoluteRank() {
|
||||
if (!rankHasBeenInitialized) {
|
||||
TrackedRace trackedRace = getTrackedLegOfCompetitorContext().getTrackedLegContext().getTrackedRaceContext().getTrackedRace();
|
||||
Competitor competitor = getTrackedLegOfCompetitorContext().getCompetitor();
|
||||
int rank = trackedRace.getRank(competitor, getManeuver().getTimePoint());
|
||||
absoluteRank = rank == 0 ? null : Double.valueOf(rank);
|
||||
rankHasBeenInitialized = true;
|
||||
}
|
||||
return absoluteRank;
|
||||
}
|
||||
|
||||
}
|
||||
+61
-22
@@ -9,7 +9,9 @@ import com.sap.sailing.domain.base.Course;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Speed;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
@@ -38,12 +40,37 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
|
||||
public Competitor getCompetitor() {
|
||||
return competitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCompetitorSearchTag() {
|
||||
return getCompetitor().getSearchTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tack getTackAtStart() throws NoWindException {
|
||||
TimePoint startOfRace = getTrackedRace().getStartOfRace();
|
||||
return startOfRace == null ? null : getTrackedRace().getTack(getCompetitor(), startOfRace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceToStartLineAtStart() {
|
||||
return getTrackedRace().getDistanceToStartLine(getCompetitor(), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getNormalizedDistanceToStarboardSideAtStart() {
|
||||
TrackedRace trackedRace = getTrackedRace();
|
||||
TrackedLegOfCompetitor firstTrackedLegOfCompetitor = trackedRace.getTrackedLeg(competitor, trackedRace.getRace().getCourse().getFirstLeg());
|
||||
TimePoint competitorStartTime = firstTrackedLegOfCompetitor.getStartTime();
|
||||
if (competitorStartTime == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Double distance = trackedRace.getDistanceFromStarboardSideOfStartLine(getCompetitor(), competitorStartTime).getMeters();
|
||||
Double length = trackedRace.getStartLine(competitorStartTime).getLength().getMeters();
|
||||
return distance / length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeedWhenStarting() {
|
||||
return getTrackedRace().getSpeedWhenCrossingStartLine(getCompetitor());
|
||||
@@ -54,12 +81,45 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
|
||||
return getTrackedRace().getSpeed(getCompetitor(), TimeUnit.SECONDS.toMillis(10));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Speed getSpeedTenSecondsAfterStart() {
|
||||
TimePoint startOfRace = getTrackedRace().getStartOfRace();
|
||||
if (startOfRace == null) {
|
||||
return null;
|
||||
}
|
||||
return getTrackedRace().getTrack(getCompetitor()).getEstimatedSpeed(startOfRace.plus(TimeUnit.SECONDS.toMillis(10)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getAbsoluteRankThirtySecondsAfterStart() {
|
||||
TimePoint startOfRace = getTrackedRace().getStartOfRace();
|
||||
if (startOfRace == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int rank = getTrackedRace().getRank(getCompetitor(), startOfRace.plus(TimeUnit.SECONDS.toMillis(30)));
|
||||
return rank == 0 ? null : Double.valueOf(rank);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getRankAtFirstMark() {
|
||||
Course course = getTrackedRace().getRace().getCourse();
|
||||
Waypoint firstMark = course.getFirstLeg().getTo();
|
||||
Competitor competitor = getCompetitor();
|
||||
return Double.valueOf(getTrackedRace().getRank(competitor, getTrackedRace().getMarkPassing(competitor, firstMark).getTimePoint()));
|
||||
int rank = getTrackedRace().getRank(competitor, getTrackedRace().getMarkPassing(competitor, firstMark).getTimePoint());
|
||||
return rank == 0 ? null : Double.valueOf(rank);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getRankGainsOrLossesBetweenFirstMarkAndFinish() {
|
||||
Double rankAtFirstMark = getRankAtFirstMark();
|
||||
Double rankAtFinish = getRankAtFinish();
|
||||
return rankAtFirstMark != null && rankAtFinish != null ? rankAtFirstMark - rankAtFinish : null;
|
||||
}
|
||||
|
||||
private Double getRankAtFinish() {
|
||||
int rank = getTrackedRace().getRank(getCompetitor(), getTrackedRace().getEndOfTracking());
|
||||
return rank == 0 ? null : Double.valueOf(rank);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,26 +152,5 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getRankGainsOrLossesBetweenFirstMarkAndFinish() {
|
||||
Double rankAtFirstMark = getRankAtFirstMark();
|
||||
Double rankAtFinish = getRankAtFinish();
|
||||
return rankAtFirstMark - rankAtFinish;
|
||||
}
|
||||
|
||||
private Double getRankAtFinish() {
|
||||
return Double.valueOf(getTrackedRace().getRank(getCompetitor(), getTrackedRace().getEndOfTracking()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getNormalizedDistanceToStarboardSideAtStart() {
|
||||
TrackedRace trackedRace = getTrackedRace();
|
||||
TrackedLegOfCompetitor firstTrackedLegOfCompetitor = trackedRace.getTrackedLeg(competitor, trackedRace.getRace().getCourse().getFirstLeg());
|
||||
TimePoint competitorStartTime = firstTrackedLegOfCompetitor.getStartTime();
|
||||
Double distance = trackedRace.getDistanceFromStarboardSideOfStartLine(getCompetitor(), competitorStartTime).getMeters();
|
||||
Double length = trackedRace.getStartLine(competitorStartTime).getLength().getMeters();
|
||||
return distance / length;
|
||||
}
|
||||
|
||||
}
|
||||
+25
-12
@@ -62,17 +62,17 @@ public class RaceResultOfCompetitorWithContext implements HasRaceResultOfCompeti
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getRelativeRank() {
|
||||
Leaderboard leaderboard = getLeaderboard();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
double competitorCount = Util.size(leaderboard.getCompetitors());
|
||||
double points = leaderboard.getTotalPoints(competitor, raceColumn, now);
|
||||
double relativeLowPoints = leaderboard.getScoringScheme().isHigherBetter() ?
|
||||
competitorCount - points : points;
|
||||
final double result = relativeLowPoints / competitorCount;
|
||||
public String getRegattaName() {
|
||||
Leaderboard leaderboard = getLeaderboard();;
|
||||
final String result = leaderboard.getName();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCompetitorSearchTag() {
|
||||
return getCompetitor().getSearchTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAverageWindSpeedInRoundedBeaufort() {
|
||||
Speed exactResult = getAverageWindSpeed();
|
||||
@@ -157,10 +157,23 @@ public class RaceResultOfCompetitorWithContext implements HasRaceResultOfCompeti
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRegattaName() {
|
||||
Leaderboard leaderboard = getLeaderboard();;
|
||||
final String result = leaderboard.getName();
|
||||
return result;
|
||||
public Double getRelativeRank() {
|
||||
Leaderboard leaderboard = getLeaderboard();
|
||||
final TimePoint now = MillisecondsTimePoint.now();
|
||||
double competitorCount = Util.size(leaderboard.getCompetitors());
|
||||
Double points = leaderboard.getTotalPoints(competitor, raceColumn, now);
|
||||
if (points != null) {
|
||||
double relativeLowPoints = leaderboard.getScoringScheme().isHigherBetter() ? competitorCount - points
|
||||
: points;
|
||||
final double result = relativeLowPoints / competitorCount;
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getAbsoluteRank() {
|
||||
return getLeaderboard().getTotalPoints(competitor, raceColumn, MillisecondsTimePoint.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+48
-4
@@ -4,9 +4,11 @@ import com.sap.sailing.datamining.data.HasTrackedLegContext;
|
||||
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompetitorContext {
|
||||
|
||||
@@ -15,6 +17,11 @@ public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompeti
|
||||
private final TrackedLegOfCompetitor trackedLegOfCompetitor;
|
||||
private final Competitor competitor;
|
||||
|
||||
private Double rankAtStart;
|
||||
private boolean isRankAtStartInitialized;
|
||||
private Double rankAtFinish;
|
||||
private boolean isRankAtFinishInitialized;
|
||||
|
||||
public TrackedLegOfCompetitorWithContext(HasTrackedLegContext trackedLegContext, TrackedLegOfCompetitor trackedLegOfCompetitor) {
|
||||
this.trackedLegContext = trackedLegContext;
|
||||
this.trackedLegOfCompetitor = trackedLegOfCompetitor;
|
||||
@@ -35,6 +42,11 @@ public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompeti
|
||||
public Competitor getCompetitor() {
|
||||
return competitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCompetitorSearchTag() {
|
||||
return getCompetitor().getSearchTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceTraveled() {
|
||||
@@ -44,10 +56,42 @@ public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompeti
|
||||
|
||||
@Override
|
||||
public Double getRankGainsOrLosses() {
|
||||
TrackedRace trackedRace = getTrackedLegContext().getTrackedRaceContext().getTrackedRace();
|
||||
Double rankAtStart = Double.valueOf(trackedRace.getRank(getCompetitor(), getTrackedLegOfCompetitor().getStartTime()));
|
||||
Double rankAtFinish = Double.valueOf(trackedRace.getRank(getCompetitor(), getTrackedLegOfCompetitor().getFinishTime()));
|
||||
return rankAtStart - rankAtFinish;
|
||||
Double rankAtStart = getRankAtStart();
|
||||
Double rankAtFinish = getRankAtFinish();
|
||||
return rankAtStart != null && rankAtFinish != null ? rankAtStart - rankAtFinish : null;
|
||||
}
|
||||
|
||||
private Double getRankAtStart() {
|
||||
if (!isRankAtStartInitialized) {
|
||||
TrackedRace trackedRace = getTrackedLegContext().getTrackedRaceContext().getTrackedRace();
|
||||
int rank = trackedRace.getRank(getCompetitor(), getTrackedLegOfCompetitor().getStartTime());
|
||||
rankAtStart = rank == 0 ? null : Double.valueOf(rank);
|
||||
isRankAtStartInitialized = true;
|
||||
}
|
||||
return rankAtStart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getRelativeRank() {
|
||||
Leaderboard leaderboard = getTrackedLegContext().getTrackedRaceContext().getLeaderboardContext().getLeaderboard();
|
||||
double competitorCount = Util.size(leaderboard.getCompetitors());
|
||||
Double rankAtFinish = getRankAtFinish();
|
||||
return rankAtFinish == null ? null : rankAtFinish / competitorCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getAbsoluteRank() {
|
||||
return getRankAtFinish();
|
||||
}
|
||||
|
||||
private Double getRankAtFinish() {
|
||||
if (!isRankAtFinishInitialized) {
|
||||
TrackedRace trackedRace = getTrackedLegContext().getTrackedRaceContext().getTrackedRace();
|
||||
int rank = trackedRace.getRank(getCompetitor(), getTrackedLegOfCompetitor().getFinishTime());
|
||||
rankAtFinish = rank == 0 ? null : Double.valueOf(rank);
|
||||
isRankAtFinishInitialized = true;
|
||||
}
|
||||
return rankAtFinish;
|
||||
}
|
||||
|
||||
}
|
||||
+10
-10
@@ -113,20 +113,20 @@ public enum BoatClassMasterdata {
|
||||
|
||||
private final String displayName;
|
||||
private final String[] alternativeNames;
|
||||
private final double hullLengthInMeter;
|
||||
private final double hullBeamInMeter;
|
||||
private final double hullLengthInMeters;
|
||||
private final double hullBeamInMeters;
|
||||
private final BoatHullType hullType;
|
||||
private final boolean typicallyStartsUpwind;
|
||||
private final boolean hasAdditionalDownwindSail;
|
||||
|
||||
private static Map<String, BoatClassMasterdata> fromUnifiedDisplayAndAlternativeNamesToBoatClassMasterdata;
|
||||
|
||||
private BoatClassMasterdata(String displayName, boolean typicallyStartsUpwind, double hullLengthInMeter,
|
||||
double hullBeamInMeter, BoatHullType hullType, boolean hasAdditionalDownwindSail, String... alternativeNames) {
|
||||
private BoatClassMasterdata(String displayName, boolean typicallyStartsUpwind, double hullLengthInMeters,
|
||||
double hullBeamInMeters, BoatHullType hullType, boolean hasAdditionalDownwindSail, String... alternativeNames) {
|
||||
this.displayName = displayName;
|
||||
this.typicallyStartsUpwind = typicallyStartsUpwind;
|
||||
this.hullLengthInMeter = hullLengthInMeter;
|
||||
this.hullBeamInMeter = hullBeamInMeter;
|
||||
this.hullLengthInMeters = hullLengthInMeters;
|
||||
this.hullBeamInMeters = hullBeamInMeters;
|
||||
this.hullType = hullType;
|
||||
this.hasAdditionalDownwindSail = hasAdditionalDownwindSail;
|
||||
this.alternativeNames = alternativeNames;
|
||||
@@ -147,8 +147,8 @@ public enum BoatClassMasterdata {
|
||||
double hullBeamInMeter, BoatHullType hullType, boolean hasAdditionalDownwindSail) {
|
||||
this.displayName = displayName;
|
||||
this.typicallyStartsUpwind = typicallyStartsUpwind;
|
||||
this.hullLengthInMeter = hullLengthInMeter;
|
||||
this.hullBeamInMeter = hullBeamInMeter;
|
||||
this.hullLengthInMeters = hullLengthInMeter;
|
||||
this.hullBeamInMeters = hullBeamInMeter;
|
||||
this.hullType = hullType;
|
||||
this.hasAdditionalDownwindSail = hasAdditionalDownwindSail;
|
||||
this.alternativeNames = null;
|
||||
@@ -192,7 +192,7 @@ public enum BoatClassMasterdata {
|
||||
}
|
||||
|
||||
public Distance getHullLength() {
|
||||
return new MeterDistance(hullLengthInMeter);
|
||||
return new MeterDistance(hullLengthInMeters);
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
@@ -204,7 +204,7 @@ public enum BoatClassMasterdata {
|
||||
}
|
||||
|
||||
public Distance getHullBeam() {
|
||||
return new MeterDistance(hullBeamInMeter);
|
||||
return new MeterDistance(hullBeamInMeters);
|
||||
}
|
||||
|
||||
public BoatHullType getHullType() {
|
||||
|
||||
@@ -13,7 +13,7 @@ import com.sap.sse.common.Duration;
|
||||
*
|
||||
*/
|
||||
public interface Distance extends Comparable<Distance>, Serializable {
|
||||
static final Distance NULL = new Distance() {
|
||||
static class NullDistance implements Distance {
|
||||
private static final long serialVersionUID = -3167560884686340893L;
|
||||
|
||||
@Override
|
||||
@@ -96,7 +96,9 @@ public interface Distance extends Comparable<Distance>, Serializable {
|
||||
public Distance abs() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static final NullDistance NULL = new NullDistance();
|
||||
|
||||
double getGeographicalMiles();
|
||||
|
||||
|
||||
@@ -17,6 +17,11 @@ public class RegattaName implements RegattaIdentifier {
|
||||
return regattaName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getRegattaName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRegatta(RegattaFetcher regattaFetcher) {
|
||||
return regattaFetcher.getRegatta(this);
|
||||
|
||||
+9
-7
@@ -2,6 +2,8 @@ package com.sap.sailing.domain.common.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
|
||||
public class BoatClassDTO extends NamedDTO implements Serializable, Comparable<BoatClassDTO> {
|
||||
private static final long serialVersionUID = 1981789833769906676L;
|
||||
|
||||
@@ -11,24 +13,24 @@ public class BoatClassDTO extends NamedDTO implements Serializable, Comparable<B
|
||||
*/
|
||||
public static final String DEFAULT_NAME = "Default";
|
||||
|
||||
private double hullLengthInMeters;
|
||||
private Distance hullLength;
|
||||
private String displayName;
|
||||
|
||||
BoatClassDTO() {}
|
||||
|
||||
public BoatClassDTO(String name, String displayName, double hullLengthInMeters) {
|
||||
public BoatClassDTO(String name, String displayName, Distance hullLength) {
|
||||
super(name);
|
||||
this.hullLengthInMeters = hullLengthInMeters;
|
||||
this.hullLength = hullLength;
|
||||
}
|
||||
|
||||
public BoatClassDTO(String name, double hullLengthInMeters) {
|
||||
public BoatClassDTO(String name, Distance hullLength) {
|
||||
super(name);
|
||||
this.hullLengthInMeters = hullLengthInMeters;
|
||||
this.hullLength = hullLength;
|
||||
this.displayName = null;
|
||||
}
|
||||
|
||||
public double getHullLengthInMeters() {
|
||||
return hullLengthInMeters;
|
||||
public Distance getHullLength() {
|
||||
return hullLength;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
|
||||
+1
@@ -24,6 +24,7 @@ public enum BravoSensorDataMetadata {
|
||||
"BravoNet_Node0x0A0_Voltage", "BravoNet_Node0x0A0_Temperature", "BravoNet_Node0x0A0_Current"));
|
||||
|
||||
public final int rideHeightColumn = getColumnIndex(RIDE_HEIGHT);
|
||||
public final int columnCount = columns.size();
|
||||
|
||||
public List<String> getColumns() {
|
||||
return columns;
|
||||
|
||||
+29
@@ -1,5 +1,7 @@
|
||||
package com.sap.sailing.domain.common.tracking.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
@@ -34,4 +36,31 @@ public class DoubleVectorFixImpl implements DoubleVectorFix {
|
||||
return fixData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.hashCode(fixData);
|
||||
result = prime * result + ((timePoint == null) ? 0 : timePoint.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
DoubleVectorFixImpl other = (DoubleVectorFixImpl) obj;
|
||||
if (!Arrays.equals(fixData, other.fixData))
|
||||
return false;
|
||||
if (timePoint == null) {
|
||||
if (other.timePoint != null)
|
||||
return false;
|
||||
} else if (!timePoint.equals(other.timePoint))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1144,11 +1144,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
logger.log(Level.WARNING, "Error loading racing procedure configration for regatta.", e);
|
||||
}
|
||||
}
|
||||
final Double buoyZoneRadiusInHullLengths = (Double) dbRegatta.get(FieldNames.REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS.name());
|
||||
final Boolean useStartTimeInference = (Boolean) dbRegatta.get(FieldNames.REGATTA_USE_START_TIME_INFERENCE.name());
|
||||
final Boolean controlTrackingFromStartAndFinishTimes = (Boolean) dbRegatta.get(FieldNames.REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES.name());
|
||||
final RankingMetricConstructor rankingMetricConstructor = loadRankingMetricConstructor(dbRegatta);
|
||||
result = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, boatClass, startDate, endDate, series, /* persistent */true,
|
||||
loadScoringScheme(dbRegatta), id, courseArea, useStartTimeInference == null ? true
|
||||
loadScoringScheme(dbRegatta), id, courseArea, buoyZoneRadiusInHullLengths == null ? Regatta.DEFAULT_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS : buoyZoneRadiusInHullLengths, useStartTimeInference == null ? true
|
||||
: useStartTimeInference, controlTrackingFromStartAndFinishTimes == null ? false : controlTrackingFromStartAndFinishTimes,
|
||||
rankingMetricConstructor);
|
||||
result.setRegattaConfiguration(configuration);
|
||||
|
||||
+1
@@ -34,6 +34,7 @@ public enum FieldNames {
|
||||
REGATTA_END_DATE,
|
||||
REGATTA_SERIES,
|
||||
REGATTA_REGATTA_CONFIGURATION,
|
||||
REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS,
|
||||
REGATTA_USE_START_TIME_INFERENCE,
|
||||
REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES,
|
||||
SERIES_NAME,
|
||||
|
||||
+1
@@ -646,6 +646,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
DBObject configurationObject = (DBObject) JSON.parse(json.toString());
|
||||
dbRegatta.put(FieldNames.REGATTA_REGATTA_CONFIGURATION.name(), configurationObject);
|
||||
}
|
||||
dbRegatta.put(FieldNames.REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS.name(), regatta.getBuoyZoneRadiusInHullLengths());
|
||||
dbRegatta.put(FieldNames.REGATTA_USE_START_TIME_INFERENCE.name(), regatta.useStartTimeInference());
|
||||
dbRegatta.put(FieldNames.REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES.name(), regatta.isControlTrackingFromStartAndFinishTimes());
|
||||
dbRegatta.put(FieldNames.REGATTA_RANKING_METRIC.name(), storeRankingMetric(regatta));
|
||||
|
||||
+2
@@ -71,6 +71,8 @@ public class AbstractGPSFixStoreTest {
|
||||
MongoObjectFactoryImpl mongoOF = (MongoObjectFactoryImpl) service.getMongoObjectFactory();
|
||||
mongoOF.getGPSFixCollection().drop();
|
||||
mongoOF.getGPSFixMetadataCollection().drop();
|
||||
mongoOF.getRaceLogCollection().drop();
|
||||
mongoOF.getRegattaLogCollection().drop();
|
||||
}
|
||||
|
||||
protected void map(RegattaLog regattaLog, Competitor comp, DeviceIdentifier device, long from, long to) {
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ public class CreateAndTrackWithRaceLogTest {
|
||||
service);
|
||||
regatta = service.createRegatta(RegattaImpl.getDefaultName("regatta", "Laser"), "Laser",
|
||||
/* startDate */null, /* endDate */null, UUID.randomUUID(), Collections.<Series> singletonList(series), false,
|
||||
new HighPoint(), UUID.randomUUID(), /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new);
|
||||
new HighPoint(), UUID.randomUUID(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new);
|
||||
series.addRaceColumn(columnName, /* trackedRegattaRegistry */null);
|
||||
leaderboard = service.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "RegattaLeaderboard", new int[] {});
|
||||
adapter = RaceLogTrackingAdapterFactory.INSTANCE.getAdapter(DomainFactory.INSTANCE);
|
||||
|
||||
+657
@@ -0,0 +1,657 @@
|
||||
package com.sap.sailing.domain.racelogtracking.test.impl;
|
||||
|
||||
import static com.sap.sse.common.Util.size;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.MongoException;
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.MappingEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorSensorDataMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogCloseOpenEndedDeviceMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMarkEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorBravoMappingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Course;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Sideline;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.CourseImpl;
|
||||
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
|
||||
import com.sap.sailing.domain.base.impl.RegattaImpl;
|
||||
import com.sap.sailing.domain.base.impl.WaypointImpl;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata;
|
||||
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.common.tracking.SensorFix;
|
||||
import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl;
|
||||
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
|
||||
import com.sap.sailing.domain.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.domain.persistence.impl.CollectionNames;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.impl.MongoSensorFixStoreImpl;
|
||||
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixMapper;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneImeiServiceFinderFactory;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier;
|
||||
import com.sap.sailing.domain.racelogsensortracking.SensorFixMapperFactory;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.racelogtracking.impl.BravoDataFixMapper;
|
||||
import com.sap.sailing.domain.racelogtracking.impl.fixtracker.FixLoaderAndTracker;
|
||||
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
|
||||
import com.sap.sailing.domain.regattalog.impl.EmptyRegattaLogStore;
|
||||
import com.sap.sailing.domain.tracking.BravoFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicSensorFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.Track;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
|
||||
import com.sap.sailing.domain.tracking.impl.SensorFixTrackImpl;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Timed;
|
||||
import com.sap.sse.common.WithID;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class SensorFixStoreAndLoadTest {
|
||||
private static final long START_OF_TRACKING = 100;
|
||||
private static final long MID_OF_TRACKING = 200;
|
||||
private static final long END_OF_TRACKING = 300;
|
||||
private static final long FIX_TIMESTAMP = 110;
|
||||
private static final long FIX_TIMESTAMP2 = 120;
|
||||
private static final long FIX_TIMESTAMP3 = 210;
|
||||
private static final long AFTER_LAST_FIX = FIX_TIMESTAMP3 + 1;
|
||||
private static final double FIX_RIDE_HEIGHT = 1337.0;
|
||||
private static final double FIX_RIDE_HEIGHT2 = 1338.0;
|
||||
private static final double FIX_RIDE_HEIGHT3 = 1336.0;
|
||||
private static final double FIX_TEST_VALUE = 12.0;
|
||||
protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory();
|
||||
protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a");
|
||||
protected final DeviceIdentifier deviceTest = new SmartphoneImeiIdentifier("b");
|
||||
protected RaceLog raceLog;
|
||||
protected RegattaLog regattaLog;
|
||||
protected SensorFixStore store;
|
||||
protected final Competitor comp = DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null,
|
||||
null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null);
|
||||
protected final Competitor comp2 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp2", "comp2", null, null, null,
|
||||
null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null, null);
|
||||
protected final Mark mark = DomainFactory.INSTANCE.getOrCreateMark("mark");
|
||||
protected final Mark mark2 = DomainFactory.INSTANCE.getOrCreateMark("mark2");
|
||||
private final BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er");
|
||||
|
||||
protected final AbstractLogEventAuthor author = new LogEventAuthorImpl("author", 0);
|
||||
private DynamicTrackedRace trackedRace;
|
||||
|
||||
protected GPSFixMoving createFix(long millis, double lat, double lng, double knots, double degrees) {
|
||||
return new GPSFixMovingImpl(new DegreePosition(lat, lng), new MillisecondsTimePoint(millis),
|
||||
new KnotSpeedWithBearingImpl(knots, new DegreeBearingImpl(degrees)));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws UnknownHostException, MongoException {
|
||||
dropPersistedData();
|
||||
raceLog = new RaceLogImpl("racelog");
|
||||
raceLog.add(new RaceLogStartOfTrackingEventImpl(new MillisecondsTimePoint(START_OF_TRACKING), author, 0));
|
||||
raceLog.add(new RaceLogEndOfTrackingEventImpl(new MillisecondsTimePoint(END_OF_TRACKING), author, 0));
|
||||
|
||||
regattaLog = new RegattaLogImpl("regattalog");
|
||||
|
||||
store = new MongoSensorFixStoreImpl(PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(),
|
||||
PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(), serviceFinderFactory);
|
||||
|
||||
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(1), author,
|
||||
new MillisecondsTimePoint(1), 0, mark));
|
||||
regattaLog.add(new RegattaLogDefineMarkEventImpl(new MillisecondsTimePoint(2), author,
|
||||
new MillisecondsTimePoint(1), 0, mark2));
|
||||
Course course = new CourseImpl("course",
|
||||
Arrays.asList(new Waypoint[] { new WaypointImpl(mark), new WaypointImpl(mark2) }));
|
||||
RaceDefinition race = new RaceDefinitionImpl("race", course, boatClass, Arrays.asList(comp, comp2));
|
||||
DynamicTrackedRegatta regatta = new DynamicTrackedRegattaImpl(new RegattaImpl(EmptyRaceLogStore.INSTANCE,
|
||||
EmptyRegattaLogStore.INSTANCE, RegattaImpl.getDefaultName("regatta", boatClass.getName()), boatClass,
|
||||
/* startDate */ null, /* endDate */null, null, null, "a", null));
|
||||
trackedRace = new DynamicTrackedRaceImpl(regatta, race, Collections.<Sideline> emptyList(),
|
||||
EmptyWindStore.INSTANCE, 0, 0, 0, /* useMarkPassingCalculator */ false, OneDesignRankingMetric::new,
|
||||
mock(RaceLogResolver.class));
|
||||
}
|
||||
|
||||
private void dropPersistedData() {
|
||||
DB db = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory().getDatabase();
|
||||
db.getCollection(CollectionNames.GPS_FIXES.name()).drop();
|
||||
db.getCollection(CollectionNames.GPS_FIXES_METADATA.name()).drop();
|
||||
db.getCollection(CollectionNames.REGATTA_LOGS.name()).drop();
|
||||
db.getCollection(CollectionNames.RACE_LOGS.name()).drop();
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
dropPersistedData();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadAlreadyAddedFixes() throws InterruptedException {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
|
||||
addBravoFixes();
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 2);
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddFixesWhileTracking() throws InterruptedException {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
addBravoFixes();
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 2);
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFixesAreLoadedIfNoStoredFixIsInTimeRange() throws InterruptedException {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(AFTER_LAST_FIX), new MillisecondsTimePoint(END_OF_TRACKING)));
|
||||
|
||||
addBravoFixes();
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 0);
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixesNotInMappedTimeRangeAreIgnoredWhileTracking() throws InterruptedException {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(AFTER_LAST_FIX), new MillisecondsTimePoint(END_OF_TRACKING)));
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
addBravoFixes();
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 0);
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompetitorWithoutMappingHasNoTrack() throws InterruptedException {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
|
||||
addBravoFixes();
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
assertNull(trackedRace.getSensorTrack(comp2, BravoFixTrack.TRACK_NAME));
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceIsMappedToDifferentCompetitorsInDifferentTimeRanges() throws InterruptedException {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp2,
|
||||
device, new MillisecondsTimePoint(MID_OF_TRACKING + 1), new MillisecondsTimePoint(END_OF_TRACKING)));
|
||||
|
||||
addBravoFixes();
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 2);
|
||||
testNumberOfRawFixes(trackedRace.getSensorTrack(comp2, BravoFixTrack.TRACK_NAME), 1);
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleMappingsForOneDeviceAndCompetitor() throws InterruptedException {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(MID_OF_TRACKING + 1), new MillisecondsTimePoint(END_OF_TRACKING)));
|
||||
|
||||
addBravoFixes();
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 3);
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNothingLoadedForRevokedMapping() throws InterruptedException {
|
||||
RegattaLogDeviceCompetitorBravoMappingEventImpl mappingEvent = new RegattaLogDeviceCompetitorBravoMappingEventImpl(
|
||||
new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(START_OF_TRACKING),
|
||||
new MillisecondsTimePoint(MID_OF_TRACKING));
|
||||
regattaLog.add(mappingEvent);
|
||||
regattaLog.add(new RegattaLogRevokeEventImpl(author, mappingEvent, "Test purposes"));
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
addBravoFixes();
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
assertNull(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME));
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixesAreLoadedIfThereIsOneRevokedAndOneNonRevokedMapping() throws InterruptedException {
|
||||
// revoked mapping timestamp 100-300
|
||||
RegattaLogDeviceCompetitorBravoMappingEventImpl mappingEvent = new RegattaLogDeviceCompetitorBravoMappingEventImpl(
|
||||
new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(START_OF_TRACKING),
|
||||
new MillisecondsTimePoint(END_OF_TRACKING));
|
||||
regattaLog.add(mappingEvent);
|
||||
regattaLog.add(new RegattaLogRevokeEventImpl(author, mappingEvent, "Test purposes"));
|
||||
|
||||
// non-revoked mapping timestamp 100-200
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
addBravoFixes();
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
// Only Fixes from 100 to 200 may be included
|
||||
testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 2);
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadFixesWhenClosingEventIsRevoked() throws InterruptedException {
|
||||
UUID mappingEventId = UUID.randomUUID();
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(MillisecondsTimePoint.now(),
|
||||
new MillisecondsTimePoint(3), author, mappingEventId, comp, device, new MillisecondsTimePoint(START_OF_TRACKING),
|
||||
null));
|
||||
RegattaLogCloseOpenEndedDeviceMappingEventImpl closeEvent = new RegattaLogCloseOpenEndedDeviceMappingEventImpl(
|
||||
new MillisecondsTimePoint(4), author, mappingEventId, new MillisecondsTimePoint(MID_OF_TRACKING));
|
||||
regattaLog.add(closeEvent);
|
||||
|
||||
addBravoFixes();
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
BravoFixTrack<Competitor> bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME);
|
||||
|
||||
testNumberOfRawFixes(bravoFixTrack, 2);
|
||||
|
||||
regattaLog.add(new RegattaLogRevokeEventImpl(author, closeEvent, "Test purposes"));
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
testNumberOfRawFixes(bravoFixTrack, 3);
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBravoFixIsCorrectlyWrapped() throws InterruptedException {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
|
||||
addBravoFixes();
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
BravoFixTrack<Competitor> bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME);
|
||||
assertEquals(FIX_RIDE_HEIGHT,
|
||||
bravoFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP)).getRideHeight());
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleFixTypesAreLoadedInSeparateTracks() throws InterruptedException {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorTestMappingEventImpl(new MillisecondsTimePoint(1), author, comp,
|
||||
deviceTest, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
|
||||
addTestFixes();
|
||||
addBravoFixes();
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 2);
|
||||
testNumberOfRawFixes(trackedRace.getSensorTrack(comp, TestFixTrackImpl.TRACK_NAME), 1);
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleFixTypesAreLoadedInSeparateTracksWhileTracking() throws InterruptedException {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorTestMappingEventImpl(new MillisecondsTimePoint(1), author, comp,
|
||||
deviceTest, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
addTestFixes();
|
||||
addBravoFixes();
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
testNumberOfRawFixes(trackedRace.getSensorTrack(comp, TestFixTrackImpl.TRACK_NAME), 1);
|
||||
testNumberOfRawFixes(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME), 2);
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleFixTypesAreMappedCorrectly() throws InterruptedException {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorTestMappingEventImpl(new MillisecondsTimePoint(1), author, comp,
|
||||
deviceTest, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(END_OF_TRACKING)));
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(END_OF_TRACKING)));
|
||||
|
||||
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
|
||||
addTestFixes();
|
||||
addBravoFixes();
|
||||
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
|
||||
BravoFixTrack<Competitor> bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME);
|
||||
assertEquals(FIX_RIDE_HEIGHT,
|
||||
bravoFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP)).getRideHeight());
|
||||
assertEquals(FIX_RIDE_HEIGHT2,
|
||||
bravoFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP2)).getRideHeight());
|
||||
assertEquals(FIX_RIDE_HEIGHT3,
|
||||
bravoFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP3)).getRideHeight());
|
||||
|
||||
TestFixTrackImpl<Competitor> testFixTrack = trackedRace.getSensorTrack(comp, TestFixTrackImpl.TRACK_NAME);
|
||||
assertEquals(FIX_TEST_VALUE,
|
||||
testFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP)).getTestValue());
|
||||
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
|
||||
private void addBravoFixes() {
|
||||
store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP, FIX_RIDE_HEIGHT));
|
||||
store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2));
|
||||
store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP3, FIX_RIDE_HEIGHT3));
|
||||
}
|
||||
|
||||
private FixLoaderAndTracker createFixLoaderAndTracker() {
|
||||
|
||||
return new FixLoaderAndTracker(trackedRace, store, new SensorFixMapperFactory() {
|
||||
private TestDataFixMapper testDataFixMapper = new TestDataFixMapper();
|
||||
private BravoDataFixMapper bravoDataFixMapper = new BravoDataFixMapper();
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
public <FixT extends Timed, TrackT extends DynamicTrack<FixT>> SensorFixMapper<FixT, TrackT, Competitor> createCompetitorMapper(
|
||||
Class<? extends RegattaLogDeviceMappingEvent<?>> eventType) {
|
||||
if(bravoDataFixMapper.isResponsibleFor(eventType)) {
|
||||
return (SensorFixMapper) bravoDataFixMapper;
|
||||
}
|
||||
if(testDataFixMapper.isResponsibleFor(eventType)) {
|
||||
return (SensorFixMapper) testDataFixMapper;
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown event type");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void testNumberOfRawFixes(Track<?> track, long expected) {
|
||||
track.lockForRead();
|
||||
assertEquals(expected, size(track.getRawFixes()));
|
||||
track.unlockAfterRead();
|
||||
}
|
||||
|
||||
private DoubleVectorFix createBravoDoubleVectorFixWithRideHeight(long timestamp, double rideHeight) {
|
||||
double[] fixData = new double[BravoSensorDataMetadata.INSTANCE.columnCount];
|
||||
fixData[BravoSensorDataMetadata.INSTANCE.rideHeightColumn] = rideHeight;
|
||||
return new DoubleVectorFixImpl(new MillisecondsTimePoint(timestamp), fixData);
|
||||
}
|
||||
|
||||
private void addTestFixes() {
|
||||
store.storeFix(deviceTest, createTestDoubleVectorFixWithTestValue(FIX_TIMESTAMP, FIX_TEST_VALUE));
|
||||
}
|
||||
|
||||
private DoubleVectorFix createTestDoubleVectorFixWithTestValue(long timestamp, double testValue) {
|
||||
double[] fixData = new double[TestFixImpl.COLUMNS.size()];
|
||||
fixData[TestFixImpl.TEST_COLUMN_INDEX] = testValue;
|
||||
return new DoubleVectorFixImpl(new MillisecondsTimePoint(timestamp), fixData);
|
||||
}
|
||||
|
||||
private static class TestFixImpl implements SensorFix {
|
||||
private static final long serialVersionUID = 2033254212013220L;
|
||||
|
||||
public static final String TEST_COLUMN = "testColumn";
|
||||
public static final int TEST_COLUMN_INDEX = 1;
|
||||
|
||||
public static final List<String> COLUMNS = Collections.unmodifiableList(Arrays.asList("blub", TEST_COLUMN));
|
||||
|
||||
private final DoubleVectorFix fix;
|
||||
|
||||
public TestFixImpl(DoubleVectorFix fix) {
|
||||
this.fix = fix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double get(String valueName) {
|
||||
return fix.get(COLUMNS.indexOf(valueName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint getTimePoint() {
|
||||
return fix.getTimePoint();
|
||||
}
|
||||
|
||||
public double getTestValue() {
|
||||
return fix.get(TEST_COLUMN_INDEX);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class TestFixTrackImpl<ItemType extends WithID & Serializable> extends SensorFixTrackImpl<ItemType, TestFixImpl> {
|
||||
private static final long serialVersionUID = 5517848726454386L;
|
||||
|
||||
public static final String TRACK_NAME = "TestFixTrack";
|
||||
|
||||
public TestFixTrackImpl(ItemType trackedItem, String trackName) {
|
||||
super(trackedItem, trackName, TestFixImpl.COLUMNS,
|
||||
TRACK_NAME + " for " + trackedItem);
|
||||
}
|
||||
|
||||
public Double getTextValue(TimePoint timePoint) {
|
||||
TestFixImpl fixAfter = getFirstFixAtOrAfter(timePoint);
|
||||
if (fixAfter != null && fixAfter.getTimePoint().compareTo(timePoint) == 0) {
|
||||
// exact match of timepoint -> no interpolation necessary
|
||||
return fixAfter.getTestValue();
|
||||
}
|
||||
TestFixImpl fixBefore = getLastFixAtOrBefore(timePoint);
|
||||
if (fixBefore != null && fixBefore.getTimePoint().compareTo(timePoint) == 0) {
|
||||
// exact match of timepoint -> no interpolation necessary
|
||||
return fixBefore.getTestValue();
|
||||
}
|
||||
if (fixAfter == null || fixBefore == null) {
|
||||
// the fix is out of the TimeRange where we have fixes
|
||||
return null;
|
||||
}
|
||||
return fixBefore.getTestValue();
|
||||
}
|
||||
}
|
||||
|
||||
public class TestDataFixMapper implements SensorFixMapper<TestFixImpl, DynamicSensorFixTrack<Competitor, TestFixImpl>, Competitor> {
|
||||
|
||||
@Override
|
||||
public DynamicSensorFixTrack<Competitor, TestFixImpl> getTrack(DynamicTrackedRace race, Competitor key) {
|
||||
return race.getOrCreateSensorTrack(key, TestFixTrackImpl.TRACK_NAME,
|
||||
() -> new TestFixTrackImpl<Competitor>(key, TestFixTrackImpl.TRACK_NAME));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestFixImpl map(DoubleVectorFix fix) {
|
||||
return new TestFixImpl(fix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponsibleFor(Class<? extends RegattaLogDeviceMappingEvent<?>> eventType) {
|
||||
return RegattaLogDeviceCompetitorTestMappingEventImpl.class.isAssignableFrom(eventType);
|
||||
}
|
||||
}
|
||||
|
||||
public class RegattaLogDeviceCompetitorTestMappingEventImpl extends RegattaLogDeviceMappingEventImpl<Competitor>
|
||||
implements RegattaLogDeviceCompetitorSensorDataMappingEvent {
|
||||
private static final long serialVersionUID = -14940305448048753L;
|
||||
|
||||
|
||||
public RegattaLogDeviceCompetitorTestMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint,
|
||||
AbstractLogEventAuthor author, Serializable pId, Competitor mappedTo, DeviceIdentifier device,
|
||||
TimePoint from, TimePoint to) {
|
||||
super(createdAt, logicalTimePoint, author, pId, mappedTo, device, from, to);
|
||||
}
|
||||
|
||||
public RegattaLogDeviceCompetitorTestMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author,
|
||||
Competitor mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) {
|
||||
super(logicalTimePoint, author, mappedTo, device, from, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(RegattaLogEventVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MappingEventVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatMappingsOutsideOfTheTrackedIntervalDontCauseLoadingToFail() throws InterruptedException {
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||
device, new MillisecondsTimePoint(10), new MillisecondsTimePoint(20)));
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp2,
|
||||
deviceTest, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp2,
|
||||
deviceTest, new MillisecondsTimePoint(10), new MillisecondsTimePoint(20)));
|
||||
addBravoFixes();
|
||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||
trackedRace.attachRaceLog(raceLog);
|
||||
trackedRace.attachRegattaLog(regattaLog);
|
||||
trackedRace.waitForLoadingToFinish();
|
||||
assertNotNull(trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME));
|
||||
assertNotNull(trackedRace.getSensorTrack(comp2, BravoFixTrack.TRACK_NAME));
|
||||
fixLoaderAndTracker.stop(true);
|
||||
}
|
||||
}
|
||||
+301
@@ -0,0 +1,301 @@
|
||||
package com.sap.sailing.domain.racelogtracking.test.impl;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.MongoException;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata;
|
||||
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl;
|
||||
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
|
||||
import com.sap.sailing.domain.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.domain.persistence.impl.CollectionNames;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.impl.MongoSensorFixStoreImpl;
|
||||
import com.sap.sailing.domain.racelog.tracking.FixReceivedListener;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneImeiServiceFinderFactory;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceIdentifier;
|
||||
import com.sap.sse.common.Timed;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class SensorFixStoreTest {
|
||||
private static final long FIX_TIMESTAMP = 110;
|
||||
private static final long FIX_TIMESTAMP2 = 120;
|
||||
private static final double FIX_RIDE_HEIGHT = 1337.0;
|
||||
private static final double FIX_RIDE_HEIGHT2 = 1338.0;
|
||||
protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory();
|
||||
protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a");
|
||||
protected final DeviceIdentifier device2 = new SmartphoneImeiIdentifier("b");
|
||||
protected SensorFixStore store;
|
||||
|
||||
protected GPSFixMoving createFix(long millis, double lat, double lng, double knots, double degrees) {
|
||||
return new GPSFixMovingImpl(new DegreePosition(lat, lng), new MillisecondsTimePoint(millis),
|
||||
new KnotSpeedWithBearingImpl(knots, new DegreeBearingImpl(degrees)));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws UnknownHostException, MongoException {
|
||||
dropPersistedData();
|
||||
newStore();
|
||||
|
||||
}
|
||||
|
||||
private void newStore() {
|
||||
store = new MongoSensorFixStoreImpl(PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(),
|
||||
PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(), serviceFinderFactory);
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
dropPersistedData();
|
||||
}
|
||||
|
||||
private void dropPersistedData() {
|
||||
DB db = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory().getDatabase();
|
||||
db.getCollection(CollectionNames.GPS_FIXES.name()).drop();
|
||||
db.getCollection(CollectionNames.GPS_FIXES_METADATA.name()).drop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixIsPersisted() throws Exception {
|
||||
addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
assertEquals(1, store.getNumberOfFixes(device));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that no local caching in the store makes in seem to work but data will be lost on restart of the system.
|
||||
*/
|
||||
@Test
|
||||
public void testFixIsFoundByOtherStoreInstance() throws Exception {
|
||||
addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
|
||||
newStore();
|
||||
assertEquals(1, store.getNumberOfFixes(device));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixDataIsPreservedOnStore() throws Exception {
|
||||
DoubleVectorFix fix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
|
||||
verifySingleFix(fix, 100, 200, device, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixWithinExclusiveBoundsIsLoaded() throws Exception {
|
||||
DoubleVectorFix fix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
verifySingleFix(fix, FIX_TIMESTAMP - 1, FIX_TIMESTAMP + 1, device, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixOnInclusiveLowerBoundIsLoaded() throws Exception {
|
||||
DoubleVectorFix fix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
verifySingleFix(fix, FIX_TIMESTAMP, FIX_TIMESTAMP + 1, device, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixOnInclusiveUpperBoundIsLoaded() throws Exception {
|
||||
DoubleVectorFix fix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
verifySingleFix(fix, FIX_TIMESTAMP-1, FIX_TIMESTAMP, device, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixesOnExclusiveBoundsArentLoaded() throws Exception {
|
||||
addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
addBravoFix(device, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2);
|
||||
verifyNoFix(FIX_TIMESTAMP, FIX_TIMESTAMP2, device, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleListenerIsNotified() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener = mockFixReceivedListener();
|
||||
store.addListener(listener, device);
|
||||
DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
|
||||
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleListenersForSameDeviceAreNotified() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener1 = mockFixReceivedListener();
|
||||
FixReceivedListener<DoubleVectorFix> listener2 = mockFixReceivedListener();
|
||||
store.addListener(listener1, device);
|
||||
store.addListener(listener2, device);
|
||||
DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
|
||||
Mockito.verify(listener1, Mockito.times(1)).fixReceived(device, doubleVectorFix);
|
||||
Mockito.verify(listener2, Mockito.times(1)).fixReceived(device, doubleVectorFix);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListenerForNonMatchingDeviceIsNotNotified() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener = mockFixReceivedListener();
|
||||
store.addListener(listener, device);
|
||||
addBravoFix(device2, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
|
||||
Mockito.verifyZeroInteractions(listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyListenerForMatchingDeviceIsNotified() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener1 = mockFixReceivedListener();
|
||||
FixReceivedListener<DoubleVectorFix> listener2 = mockFixReceivedListener();
|
||||
store.addListener(listener1, device);
|
||||
store.addListener(listener2, device2);
|
||||
DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
|
||||
Mockito.verify(listener1, Mockito.times(1)).fixReceived(device, doubleVectorFix);
|
||||
Mockito.verifyZeroInteractions(listener2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListenerForMatchingDeviceIsNotifiedMultipleTimes() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener = mockFixReceivedListener();
|
||||
store.addListener(listener, device);
|
||||
DoubleVectorFix doubleVectorFix1 = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
DoubleVectorFix doubleVectorFix2 = addBravoFix(device, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2);
|
||||
|
||||
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix1);
|
||||
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix2);
|
||||
Mockito.verifyNoMoreInteractions(listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAfterRemoveListenerIsNotNotified() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener = mockFixReceivedListener();
|
||||
store.addListener(listener, device);
|
||||
store.removeListener(listener);
|
||||
addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
Mockito.verifyZeroInteractions(listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAfterRemoveForDeviceListenerIsNotNotified() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener = mockFixReceivedListener();
|
||||
store.addListener(listener, device);
|
||||
store.removeListener(listener, device);
|
||||
addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
Mockito.verifyZeroInteractions(listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAfterRemoveForNonMatchingDeviceListenerIsNotified() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener = mockFixReceivedListener();
|
||||
store.addListener(listener, device);
|
||||
store.removeListener(listener, device2);
|
||||
DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListenerForMultipleDevicesIsNotifiedMultipleTimes() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener = mockFixReceivedListener();
|
||||
store.addListener(listener, device);
|
||||
store.addListener(listener, device2);
|
||||
DoubleVectorFix doubleVectorFix1 = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
DoubleVectorFix doubleVectorFix2 = addBravoFix(device2, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2);
|
||||
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix1);
|
||||
Mockito.verify(listener, Mockito.times(1)).fixReceived(device2, doubleVectorFix2);
|
||||
Mockito.verifyNoMoreInteractions(listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAfterRemoveListenerForMultipleDevicesIsNotNotified() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener = mockFixReceivedListener();
|
||||
store.addListener(listener, device);
|
||||
store.addListener(listener, device2);
|
||||
store.removeListener(listener);
|
||||
addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
addBravoFix(device2, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2);
|
||||
Mockito.verifyZeroInteractions(listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAfterRemoveListenerForOneDevicesIsNotifiedForOtherDevice() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener = mockFixReceivedListener();
|
||||
store.addListener(listener, device);
|
||||
store.addListener(listener, device2);
|
||||
store.removeListener(listener, device);
|
||||
addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
DoubleVectorFix doubleVectorFix2 = addBravoFix(device2, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2);
|
||||
Mockito.verify(listener, Mockito.times(1)).fixReceived(device2, doubleVectorFix2);
|
||||
Mockito.verifyNoMoreInteractions(listener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAfterRemoveListenerOtherListenerIsNotified() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener1 = mockFixReceivedListener();
|
||||
FixReceivedListener<DoubleVectorFix> listener2 = mockFixReceivedListener();
|
||||
store.addListener(listener1, device);
|
||||
store.addListener(listener2, device);
|
||||
store.removeListener(listener1);
|
||||
DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
Mockito.verify(listener2, Mockito.times(1)).fixReceived(device, doubleVectorFix);
|
||||
Mockito.verifyNoMoreInteractions(listener2);
|
||||
Mockito.verifyZeroInteractions(listener1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAfterRemoveForDeviceListenerOtherListenerIsNotified() throws Exception {
|
||||
FixReceivedListener<DoubleVectorFix> listener1 = mockFixReceivedListener();
|
||||
FixReceivedListener<DoubleVectorFix> listener2 = mockFixReceivedListener();
|
||||
store.addListener(listener1, device);
|
||||
store.addListener(listener2, device);
|
||||
store.removeListener(listener1, device);
|
||||
DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
|
||||
Mockito.verify(listener2, Mockito.times(1)).fixReceived(device, doubleVectorFix);
|
||||
Mockito.verifyNoMoreInteractions(listener2);
|
||||
Mockito.verifyZeroInteractions(listener1);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private FixReceivedListener<DoubleVectorFix> mockFixReceivedListener() {
|
||||
FixReceivedListener<DoubleVectorFix> listener = Mockito.mock(FixReceivedListener.class);
|
||||
return listener;
|
||||
}
|
||||
|
||||
private void verifySingleFix(Timed expectedFix, long start, long end, DeviceIdentifier device, boolean inclusive) throws Exception {
|
||||
List<Timed> loadedFixes = loadFixes(start, end, device, inclusive);
|
||||
assertEquals(1, loadedFixes.size());
|
||||
assertEquals(expectedFix, loadedFixes.get(0));
|
||||
}
|
||||
|
||||
private void verifyNoFix(long start, long end, DeviceIdentifier device, boolean inclusive) throws Exception {
|
||||
List<Timed> loadedFixes = loadFixes(start, end, device, inclusive);
|
||||
assertEquals(0, loadedFixes.size());
|
||||
}
|
||||
|
||||
private List<Timed> loadFixes(long start, long end, DeviceIdentifier device, boolean inclusive)
|
||||
throws TransformationException {
|
||||
List<Timed> loadedFixes = new ArrayList<>();
|
||||
|
||||
store.loadFixes(loadedFixes::add, device, new MillisecondsTimePoint(start), new MillisecondsTimePoint(end), inclusive);
|
||||
return loadedFixes;
|
||||
}
|
||||
|
||||
private DoubleVectorFix addBravoFix(DeviceIdentifier device, long timestamp, double rideHeight) {
|
||||
DoubleVectorFix fix = createBravoDoubleVectorFixWithRideHeight(timestamp, rideHeight);
|
||||
store.storeFix(device, fix);
|
||||
return fix;
|
||||
}
|
||||
|
||||
private DoubleVectorFix createBravoDoubleVectorFixWithRideHeight(long timestamp, double rideHeight) {
|
||||
double[] fixData = new double[BravoSensorDataMetadata.INSTANCE.columnCount];
|
||||
fixData[BravoSensorDataMetadata.INSTANCE.rideHeightColumn] = rideHeight;
|
||||
return new DoubleVectorFixImpl(new MillisecondsTimePoint(timestamp), fixData);
|
||||
}
|
||||
}
|
||||
+4
@@ -6,11 +6,13 @@ import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.common.tracking.impl.CompactGPSFixImpl;
|
||||
import com.sap.sailing.domain.common.tracking.impl.CompactGPSFixMovingImpl;
|
||||
import com.sap.sailing.domain.common.tracking.impl.DoubleVectorFixImpl;
|
||||
import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl;
|
||||
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
|
||||
import com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl;
|
||||
import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.FixMongoHandler;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.impl.DoubleVectorFixMongoHandlerImpl;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.impl.GPSFixMongoHandlerImpl;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.impl.GPSFixMovingMongoHandlerImpl;
|
||||
import com.sap.sse.common.TypeBasedServiceFinder;
|
||||
@@ -20,6 +22,7 @@ public class MockGPSFixMongoServiceFinder implements TypeBasedServiceFinder<FixM
|
||||
private final DomainObjectFactoryImpl dof = new DomainObjectFactoryImpl(null, null);
|
||||
private final FixMongoHandler<?> movingHandler = new GPSFixMovingMongoHandlerImpl(mof, dof);
|
||||
private final FixMongoHandler<?> handler = new GPSFixMongoHandlerImpl(mof, dof);
|
||||
private final FixMongoHandler<?> doubleVectorFixHandler = new DoubleVectorFixMongoHandlerImpl(mof, dof);
|
||||
|
||||
@Override
|
||||
public FixMongoHandler<?> findService(String fixType) {
|
||||
@@ -27,6 +30,7 @@ public class MockGPSFixMongoServiceFinder implements TypeBasedServiceFinder<FixM
|
||||
fixType.equals(CompactGPSFixMovingImpl.class.getName())) return movingHandler;
|
||||
if (fixType.equals(GPSFixImpl.class.getName()) ||
|
||||
fixType.equals(CompactGPSFixImpl.class.getName())) return handler;
|
||||
if (fixType.equals(DoubleVectorFixImpl.class.getName())) return doubleVectorFixHandler;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-08-12T10:46:08Z" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages.properties" source-language="en" target-language="ja">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-09-29T12:18:02Z" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages.properties" source-language="en" target-language="ja">
|
||||
<header>
|
||||
<skl>
|
||||
<internal-file crc="cdbdcb19e10086d34f715e2a7da26eef" form="base64">H4sIAAAAAAAAAF2RTU/DMAyG7/0VvnGZEGekHgYSUiVgY+3gnLXeajWNo9jbqBD/naQtbOLm+PXH+zgaTN2ROxTuRGqU2D1xyKs5C5c07DlkUhv3tnnkBlfhnYR0G2zFGzyQKIal5C+mQ5BjQBj4CK05IWiL8HX3DUvvgZyosRabW6hadJDmjQV7tpbPaeM0HjhAbanuRtWS6+AoSY5jA0hvgvqWXZzOEOb1YCQ7o625x4rzjymKBRmtyq1gkLzU2AfxmcxkxjWBqbmWllNqkm2c6SL7Ce0wwlYtyXO0khf7Ec9EzICmSb40atAbssATUYMnqhHOpO34TvjGpvLhcoYFCPXeDjPrDuMREpIkN/fZ7shDha7BkKcQdIwz432pHLCYxlT4qclSw+5GLzdPCwfUBXiLRvB36X1qL1jyuftyDu9n/D/p+hzJwDqSxm/2/tX0mJfLNZSROOE/JHuTnEnMFa6kQ6v/S2HOZz95rIJYdwIAAA==</internal-file>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-08-12T11:07:55Z" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages.properties" source-language="en" target-language="ru">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-09-29T12:18:02Z" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages.properties" source-language="en" target-language="ru">
|
||||
<header>
|
||||
<skl>
|
||||
<internal-file crc="cdbdcb19e10086d34f715e2a7da26eef" form="base64">H4sIAAAAAAAAAF2RTU/DMAyG7/0VvnGZEGekHgYSUiVgY+3gnLXeajWNo9jbqBD/naQtbOLm+PXH+zgaTN2ROxTuRGqU2D1xyKs5C5c07DlkUhv3tnnkBlfhnYR0G2zFGzyQKIal5C+mQ5BjQBj4CK05IWiL8HX3DUvvgZyosRabW6hadJDmjQV7tpbPaeM0HjhAbanuRtWS6+AoSY5jA0hvgvqWXZzOEOb1YCQ7o625x4rzjymKBRmtyq1gkLzU2AfxmcxkxjWBqbmWllNqkm2c6SL7Ce0wwlYtyXO0khf7Ec9EzICmSb40atAbssATUYMnqhHOpO34TvjGpvLhcoYFCPXeDjPrDuMREpIkN/fZ7shDha7BkKcQdIwz432pHLCYxlT4qclSw+5GLzdPCwfUBXiLRvB36X1qL1jyuftyDu9n/D/p+hzJwDqSxm/2/tX0mJfLNZSROOE/JHuTnEnMFa6kQ6v/S2HOZz95rIJYdwIAAA==</internal-file>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-08-12T11:07:55Z" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages.properties" source-language="en" target-language="zh-CN">
|
||||
<file datatype="javapropertyresourcebundle" date="2016-09-29T12:18:02Z" original="/usr/sap/ljs/app/Converter_5483050776164983/java/com.sap.sailing.domain.racelogtrackingadapter/resources/stringmessages/TrackingStringMessages.properties" source-language="en" target-language="zh-CN">
|
||||
<header>
|
||||
<skl>
|
||||
<internal-file crc="cdbdcb19e10086d34f715e2a7da26eef" form="base64">H4sIAAAAAAAAAF2RTU/DMAyG7/0VvnGZEGekHgYSUiVgY+3gnLXeajWNo9jbqBD/naQtbOLm+PXH+zgaTN2ROxTuRGqU2D1xyKs5C5c07DlkUhv3tnnkBlfhnYR0G2zFGzyQKIal5C+mQ5BjQBj4CK05IWiL8HX3DUvvgZyosRabW6hadJDmjQV7tpbPaeM0HjhAbanuRtWS6+AoSY5jA0hvgvqWXZzOEOb1YCQ7o625x4rzjymKBRmtyq1gkLzU2AfxmcxkxjWBqbmWllNqkm2c6SL7Ce0wwlYtyXO0khf7Ec9EzICmSb40atAbssATUYMnqhHOpO34TvjGpvLhcoYFCPXeDjPrDuMREpIkN/fZ7shDha7BkKcQdIwz432pHLCYxlT4qclSw+5GLzdPCwfUBXiLRvB36X1qL1jyuftyDu9n/D/p+hzJwDqSxm/2/tX0mJfLNZSROOE/JHuTnEnMFa6kQ6v/S2HOZz95rIJYdwIAAA==</internal-file>
|
||||
|
||||
-1
@@ -48,7 +48,6 @@ public class EndOfTrackingController extends AbstractRaceChangeListener {
|
||||
if (!Util.equalsWithNull(trackedRace.getEndOfTracking(), newEndOfTracking)) {
|
||||
raceLog.add(new RaceLogEndOfTrackingEventImpl(newEndOfTracking,
|
||||
raceLogEventAuthor, raceLog.getCurrentPassId()));
|
||||
trackedRace.updateStartAndEndOfTracking(/* waitForGPSFixesToLoad */ false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -46,7 +46,6 @@ public class StartOfTrackingController implements StartTimeChangedListener {
|
||||
if (!Util.equalsWithNull(trackedRace.getStartOfTracking(), newStartOfTracking)) {
|
||||
raceLog.add(new RaceLogStartOfTrackingEventImpl(newStartOfTracking,
|
||||
raceLogEventAuthor, raceLog.getCurrentPassId()));
|
||||
trackedRace.updateStartAndEndOfTracking(/* waitForGPSFixesToLoad */ false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+37
-25
@@ -161,6 +161,9 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
|
||||
}
|
||||
|
||||
private void loadFixes(TimeRange timeRangeToLoad, DeviceMappingWithRegattaLogEvent<? extends WithID> mapping) {
|
||||
if(timeRangeToLoad == null) {
|
||||
return;
|
||||
}
|
||||
if (preemptiveStopRequested.get()) {
|
||||
return;
|
||||
}
|
||||
@@ -194,8 +197,8 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
|
||||
try {
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
DeviceMapping<Competitor> competitorMapping = (DeviceMapping<Competitor>) mapping;
|
||||
gpsFixStore.loadCompetitorTrack(track, competitorMapping, getStartOfTracking(),
|
||||
getEndOfTracking());
|
||||
gpsFixStore.loadCompetitorTrack(track, competitorMapping, timeRangeToLoad.from(),
|
||||
timeRangeToLoad.to());
|
||||
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
|
||||
logger.log(Level.WARNING, "Could not load competitor track " + mapping.getMappedTo());
|
||||
}
|
||||
@@ -208,12 +211,10 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
DeviceMapping<Mark> markMapping = (DeviceMapping<Mark>) mapping;
|
||||
TimePoint from = getStartOfTracking();
|
||||
TimePoint to = getEndOfTracking();
|
||||
gpsFixStore.loadMarkTrack(track, markMapping, from, to);
|
||||
gpsFixStore.loadMarkTrack(track, markMapping, timeRangeToLoad.from(), timeRangeToLoad.to());
|
||||
if (track.getFirstRawFix() == null) {
|
||||
logger.fine("Loading mark positions from outside of start/end of tracking interval (" + from
|
||||
+ ".." + to + ") because no fixes were found in that interval");
|
||||
logger.fine("Loading mark positions from outside of start/end of tracking interval (" + timeRangeToLoad.from()
|
||||
+ ".." + timeRangeToLoad.to() + ") because no fixes were found in that interval");
|
||||
// got an empty track for the mark; try again without constraining the mapping interval
|
||||
// by start/end of tracking to at least attempt to get fixes at all in case there were any
|
||||
// within the device mapping interval specified
|
||||
@@ -264,12 +265,10 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
|
||||
}
|
||||
}
|
||||
|
||||
// TEMP: kommt von RaceLogSensorFixTracker
|
||||
protected TimePoint getStartOfTracking() {
|
||||
return trackedRace.getStartOfTracking();
|
||||
}
|
||||
|
||||
// TEMP: kommt von RaceLogSensorFixTracker
|
||||
protected TimePoint getEndOfTracking() {
|
||||
return trackedRace.getEndOfTracking();
|
||||
}
|
||||
@@ -277,10 +276,7 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
|
||||
protected void loadFixesForExtendedTimeRange(TimePoint loadFixesFrom, TimePoint loadFixesTo) {
|
||||
final TimeRangeImpl extendedTimeRange = new TimeRangeImpl(loadFixesFrom, loadFixesTo);
|
||||
deviceMappings.forEachMapping((mapping) -> {
|
||||
TimeRange timeRangeToLoad = extendedTimeRange.intersection(mapping.getTimeRange());
|
||||
if (timeRangeToLoad != null && !preemptiveStopRequested.get()) {
|
||||
loadFixes(timeRangeToLoad, mapping);
|
||||
}
|
||||
loadFixes(extendedTimeRange.intersection(mapping.getTimeRange()), mapping);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -292,7 +288,6 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
|
||||
* @param updateCallback
|
||||
* the {@link Runnable} callback used to run the update
|
||||
*/
|
||||
// TODO Consider using a thread pool here, after merging bug3864 into master
|
||||
private void updateAsyncInternal(final Runnable updateCallback) {
|
||||
synchronized (FixLoaderAndTracker.this) {
|
||||
activeLoaders.incrementAndGet();
|
||||
@@ -301,9 +296,9 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
|
||||
ThreadPoolUtil.INSTANCE.getDefaultForegroundTaskThreadPoolExecutor().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
trackedRace.lockForSerializationRead();
|
||||
try {
|
||||
if (!preemptiveStopRequested.get()) {
|
||||
trackedRace.lockForSerializationRead();
|
||||
setStatusAndProgress(TrackedRaceStatusEnum.LOADING, 0.5);
|
||||
synchronized (FixLoaderAndTracker.this) {
|
||||
FixLoaderAndTracker.this.notifyAll();
|
||||
@@ -311,15 +306,18 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
|
||||
updateCallback.run();
|
||||
}
|
||||
} finally {
|
||||
synchronized (FixLoaderAndTracker.this) {
|
||||
int currentActiveLoaders = activeLoaders.decrementAndGet();
|
||||
FixLoaderAndTracker.this.notifyAll();
|
||||
if (currentActiveLoaders == 0) {
|
||||
setStatusAndProgress(stopRequested.get() ? TrackedRaceStatusEnum.FINISHED
|
||||
: TrackedRaceStatusEnum.TRACKING, 1.0);
|
||||
try {
|
||||
synchronized (FixLoaderAndTracker.this) {
|
||||
int currentActiveLoaders = activeLoaders.decrementAndGet();
|
||||
FixLoaderAndTracker.this.notifyAll();
|
||||
if (currentActiveLoaders == 0) {
|
||||
setStatusAndProgress(stopRequested.get() ? TrackedRaceStatusEnum.FINISHED
|
||||
: TrackedRaceStatusEnum.TRACKING, 1.0);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
trackedRace.unlockAfterSerializationRead();
|
||||
}
|
||||
trackedRace.unlockAfterSerializationRead();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -350,7 +348,7 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
|
||||
@Override
|
||||
protected void mappingRemoved(DeviceMappingWithRegattaLogEvent<WithID> mapping) {
|
||||
final DeviceIdentifier device = mapping.getDevice();
|
||||
if(!hasMappingForDevice(device)) {
|
||||
if (!hasMappingForDevice(device)) {
|
||||
sensorFixStore.removeListener(listener, device);
|
||||
}
|
||||
// TODO if tracks are always associated to only one device mapping, we could remove tracks here
|
||||
@@ -366,8 +364,22 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
|
||||
@Override
|
||||
protected void mappingChanged(DeviceMappingWithRegattaLogEvent<WithID> oldMapping,
|
||||
DeviceMappingWithRegattaLogEvent<WithID> newMapping) {
|
||||
// TODO can the new time range be bigger than the old one? In this case we would need to load the
|
||||
// additional time range.
|
||||
final TimeRange newTimeRange = newMapping.getTimeRange();
|
||||
final TimeRange oldTimeRange = oldMapping.getTimeRange();
|
||||
if(newTimeRange.endsAfter(oldTimeRange)) {
|
||||
final TimePoint oldTo= oldTimeRange.to();
|
||||
final TimePoint newFrom = newTimeRange.from();
|
||||
final TimePoint from = oldTo.after(newFrom) ? oldTo : newFrom;
|
||||
final TimeRange rangeToLoad = new TimeRangeImpl(from, newTimeRange.to());
|
||||
loadFixes(rangeToLoad, newMapping);
|
||||
}
|
||||
if(newTimeRange.startsBefore(oldTimeRange)) {
|
||||
final TimePoint oldFrom= oldTimeRange.from();
|
||||
final TimePoint newTo = newTimeRange.to();
|
||||
final TimePoint to = oldFrom.after(newTo) ? oldFrom : newTo;
|
||||
final TimeRange rangeToLoad = new TimeRangeImpl(newTimeRange.from(), to);
|
||||
loadFixes(rangeToLoad, newMapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-5
@@ -120,7 +120,7 @@ public class RaceLogFixTrackerManager implements TrackingDataLoader {
|
||||
stopTrackerIfStillRunning(preemptive);
|
||||
trackedRace.removeListener(raceChangeListener);
|
||||
synchronized (knownRaceLogs) {
|
||||
for (RaceLog raceLog : trackedRace.getAttachedRaceLogs()) {
|
||||
for (RaceLog raceLog : knownRaceLogs) {
|
||||
removeRaceLogUnlocked(raceLog);
|
||||
}
|
||||
}
|
||||
@@ -142,10 +142,12 @@ public class RaceLogFixTrackerManager implements TrackingDataLoader {
|
||||
}
|
||||
|
||||
boolean isForTracking() {
|
||||
for (RaceLog raceLog : trackedRace.getAttachedRaceLogs()) {
|
||||
RaceLogTrackingState raceLogTrackingState = new RaceLogTrackingStateAnalyzer(raceLog).analyze();
|
||||
if (raceLogTrackingState.isForTracking()) {
|
||||
return true;
|
||||
synchronized (knownRaceLogs) {
|
||||
for (RaceLog raceLog : knownRaceLogs) {
|
||||
RaceLogTrackingState raceLogTrackingState = new RaceLogTrackingStateAnalyzer(raceLog).analyze();
|
||||
if (raceLogTrackingState.isForTracking()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
+50
-25
@@ -48,7 +48,7 @@ public abstract class RegattaLogDeviceMappings<ItemT extends WithID> {
|
||||
* sure to not produce a memory leak.
|
||||
*/
|
||||
private final Set<RegattaLog> knownRegattaLogs = new HashSet<>();
|
||||
|
||||
|
||||
/**
|
||||
* Lock object to be used when accessing {@link #knownRegattaLogs}.
|
||||
*/
|
||||
@@ -127,16 +127,16 @@ public abstract class RegattaLogDeviceMappings<ItemT extends WithID> {
|
||||
knownRegattaLogs.forEach((log) -> log.removeListener(regattaLogEventVisitor));
|
||||
knownRegattaLogs.clear();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateMappings() {
|
||||
try {
|
||||
updateMappings(true);
|
||||
updateMappingsInternal();
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Could not update device mappings", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls the given callback for every known mapping that's currently known.
|
||||
*
|
||||
@@ -163,11 +163,11 @@ public abstract class RegattaLogDeviceMappings<ItemT extends WithID> {
|
||||
public void forEachMapping(BiConsumer<ItemT, DeviceMappingWithRegattaLogEvent<ItemT>> callback) {
|
||||
LockUtil.executeWithReadLock(mappingsLock, () -> {
|
||||
for (Map.Entry<ItemT, List<DeviceMappingWithRegattaLogEvent<ItemT>>> entry : mappings.entrySet()) {
|
||||
ItemT item = entry.getKey();
|
||||
for (DeviceMappingWithRegattaLogEvent<ItemT> mapping : entry.getValue()) {
|
||||
callback.accept(item, mapping);
|
||||
}
|
||||
ItemT item = entry.getKey();
|
||||
for (DeviceMappingWithRegattaLogEvent<ItemT> mapping : entry.getValue()) {
|
||||
callback.accept(item, mapping);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -187,13 +187,13 @@ public abstract class RegattaLogDeviceMappings<ItemT extends WithID> {
|
||||
Consumer<DeviceMappingWithRegattaLogEvent<ItemT>> callback) {
|
||||
LockUtil.executeWithReadLock(mappingsLock, () -> {
|
||||
List<DeviceMappingWithRegattaLogEvent<ItemT>> mappingsForDevice = mappingsByDevice.get(device);
|
||||
if (mappingsForDevice != null) {
|
||||
for (DeviceMappingWithRegattaLogEvent<ItemT> mapping : mappingsForDevice) {
|
||||
if (mapping.getTimeRange().includes(timePoint)) {
|
||||
callback.accept(mapping);
|
||||
}
|
||||
if (mappingsForDevice != null) {
|
||||
for (DeviceMappingWithRegattaLogEvent<ItemT> mapping : mappingsForDevice) {
|
||||
if (mapping.getTimeRange().includes(timePoint)) {
|
||||
callback.accept(mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -236,9 +236,7 @@ public abstract class RegattaLogDeviceMappings<ItemT extends WithID> {
|
||||
*
|
||||
* @throws DoesNotHaveRegattaLogException
|
||||
*/
|
||||
private final <FixT extends Timed, TrackT extends DynamicTrack<FixT>> void updateMappings(boolean loadIfNotCovered) {
|
||||
// TODO remove fixes, if mappings have been removed
|
||||
// check if there are new time ranges not covered so far
|
||||
private final <FixT extends Timed, TrackT extends DynamicTrack<FixT>> void updateMappingsInternal() {
|
||||
final Map<ItemT, List<DeviceMappingWithRegattaLogEvent<ItemT>>> newMappings = calculateMappings();
|
||||
final Map<ItemT, List<DeviceMappingWithRegattaLogEvent<ItemT>>> oldMappings = new HashMap<>();
|
||||
LockUtil.lockForWrite(mappingsLock);
|
||||
@@ -261,18 +259,20 @@ public abstract class RegattaLogDeviceMappings<ItemT extends WithID> {
|
||||
} finally {
|
||||
LockUtil.unlockAfterWrite(mappingsLock);
|
||||
}
|
||||
if (loadIfNotCovered) {
|
||||
calculateDiff(oldMappings, newMappings);
|
||||
}
|
||||
calculateDiff(oldMappings, newMappings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates <em>and applies</em> the mapping changes by removing listeners no longer needed for the mappings removed,
|
||||
* and by loading and adding the fixes for extended or added mappings.
|
||||
*/
|
||||
private void calculateDiff(Map<ItemT, List<DeviceMappingWithRegattaLogEvent<ItemT>>> previousMappings,
|
||||
Map<ItemT, List<DeviceMappingWithRegattaLogEvent<ItemT>>> newMappings) {
|
||||
Set<ItemT> itemsToProcess = new HashSet<ItemT>(previousMappings.keySet());
|
||||
itemsToProcess.addAll(newMappings.keySet());
|
||||
for (ItemT item : itemsToProcess) {
|
||||
if (!newMappings.containsKey(item)) {
|
||||
previousMappings.get(item).forEach(this::mappingRemoved);
|
||||
previousMappings.get(item).forEach(this::mappingRemovedInternal);
|
||||
} else {
|
||||
final List<DeviceMappingWithRegattaLogEvent<ItemT>> oldMappings = previousMappings.containsKey(item)
|
||||
? previousMappings.get(item) : Collections.emptyList();
|
||||
@@ -281,22 +281,30 @@ public abstract class RegattaLogDeviceMappings<ItemT extends WithID> {
|
||||
DeviceMappingWithRegattaLogEvent<ItemT> oldMapping = findAndRemoveMapping(newMapping,
|
||||
oldMappings);
|
||||
if (oldMapping == null) {
|
||||
mappingAdded(newMapping);
|
||||
} else if (newMapping.getTimeRange().equals(oldMapping.getTimeRange())) {
|
||||
mappingChanged(oldMapping, newMapping);
|
||||
mappingAddedInternal(newMapping);
|
||||
} else if (!newMapping.getTimeRange().equals(oldMapping.getTimeRange())) {
|
||||
mappingChangedInternal(oldMapping, newMapping);
|
||||
}
|
||||
}
|
||||
oldMappings.forEach(this::mappingRemoved);
|
||||
oldMappings.forEach(this::mappingRemovedInternal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called when a {@link DeviceMapping} was removed.
|
||||
*
|
||||
* @param mapping the removed mapping
|
||||
*/
|
||||
protected abstract void mappingRemoved(DeviceMappingWithRegattaLogEvent<ItemT> mapping);
|
||||
|
||||
private void mappingRemovedInternal(DeviceMappingWithRegattaLogEvent<ItemT> mapping) {
|
||||
try {
|
||||
mappingRemoved(mapping);
|
||||
} catch(Exception e) {
|
||||
logger.log(Level.SEVERE, "error while removing mapping " + mapping, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a {@link DeviceMapping} was added.
|
||||
@@ -304,6 +312,14 @@ public abstract class RegattaLogDeviceMappings<ItemT extends WithID> {
|
||||
* @param mapping the new mapping
|
||||
*/
|
||||
protected abstract void mappingAdded(DeviceMappingWithRegattaLogEvent<ItemT> mapping);
|
||||
|
||||
private void mappingAddedInternal(DeviceMappingWithRegattaLogEvent<ItemT> mapping) {
|
||||
try {
|
||||
mappingAdded(mapping);
|
||||
} catch(Exception e) {
|
||||
logger.log(Level.SEVERE, "error while adding mapping " + mapping, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a {@link DeviceMapping} was changed regarding its mapped time range.
|
||||
@@ -315,6 +331,15 @@ public abstract class RegattaLogDeviceMappings<ItemT extends WithID> {
|
||||
protected abstract void mappingChanged(DeviceMappingWithRegattaLogEvent<ItemT> oldMapping,
|
||||
DeviceMappingWithRegattaLogEvent<ItemT> newMapping);
|
||||
|
||||
private void mappingChangedInternal(DeviceMappingWithRegattaLogEvent<ItemT> oldMapping,
|
||||
DeviceMappingWithRegattaLogEvent<ItemT> newMapping) {
|
||||
try {
|
||||
mappingChanged(oldMapping, newMapping);
|
||||
} catch(Exception e) {
|
||||
logger.log(Level.SEVERE, "error while changing mapping old: " + oldMapping + "; new: " + newMapping, e);
|
||||
}
|
||||
}
|
||||
|
||||
private DeviceMappingWithRegattaLogEvent<ItemT> findAndRemoveMapping(
|
||||
DeviceMappingWithRegattaLogEvent<ItemT> mappingToFind,
|
||||
List<DeviceMappingWithRegattaLogEvent<ItemT>> newItemsToProcess) {
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ public abstract class BaseRegattaLogDeviceMappingFinder<ItemT extends WithID>
|
||||
if (!endOfFirstHalf.before(from)) {
|
||||
log.add(createDeviceMappingEvent(item, event.getAuthor(), from, endOfFirstHalf, event.getDevice()));
|
||||
}
|
||||
if (!to.before(startOfSecondHalf)) {
|
||||
if (to == null || !to.before(startOfSecondHalf)) {
|
||||
log.add(createDeviceMappingEvent(item, event.getAuthor(), startOfSecondHalf, to,
|
||||
event.getDevice()));
|
||||
}
|
||||
|
||||
+1
-1
@@ -250,7 +250,7 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab
|
||||
c.getFlagImage() == null ? null : c.getFlagImage().toString(),
|
||||
new BoatDTO(c.getBoat().getName(), c.getBoat().getSailID(), c.getBoat().getColor()),
|
||||
new BoatClassDTO(c.getBoat().getBoatClass()
|
||||
.getName(), c.getBoat().getBoatClass().getDisplayName(), c.getBoat().getBoatClass().getHullLength().getMeters()),
|
||||
.getName(), c.getBoat().getBoatClass().getDisplayName(), c.getBoat().getBoatClass().getHullLength()),
|
||||
c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile(), c.getSearchTag());
|
||||
weakCompetitorDTOCache.put(c, competitorDTO);
|
||||
}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ public class WaypointImpl implements Waypoint {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
return (getName()==null?"":getName()) + " ("+getPassingInstructions()+")";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-4
@@ -35,6 +35,7 @@ import com.sap.sailing.domain.common.dto.LeaderboardRowDTO;
|
||||
import com.sap.sailing.domain.common.dto.LegEntryDTO;
|
||||
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
|
||||
import com.sap.sailing.domain.common.dto.RaceDTO;
|
||||
import com.sap.sailing.domain.common.impl.MeterDistance;
|
||||
import com.sap.sailing.domain.test.StoredTrackBasedTest;
|
||||
import com.sap.sse.common.Cloner;
|
||||
import com.sap.sse.common.Color;
|
||||
@@ -234,7 +235,7 @@ public class LeaderboardDTODiffingTest {
|
||||
public void testCompetitorListChange() {
|
||||
newVersion.competitors = new ArrayList<CompetitorDTO>(newVersion.competitors); // clone competitor list so it's not identical to that of previous version
|
||||
CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987",
|
||||
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null,
|
||||
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", new MeterDistance(5.05)), /* timeOnTimeFactor */ null,
|
||||
/* timeOnDistanceAllowancePerNauticalMile */ null, null);
|
||||
newVersion.competitors.add(13, somebodyNew); // insert a competitor; this should mess up all others' indexes; check if this works
|
||||
CompetitorDTO wolfgang = getPreviousCompetitorByName("HUNGER +JESS");
|
||||
@@ -255,7 +256,7 @@ public class LeaderboardDTODiffingTest {
|
||||
newVersion.setSuppressedCompetitors(newSuppressedCompetitors);
|
||||
newVersion.competitors = new ArrayList<CompetitorDTO>(newVersion.competitors); // clone competitor list so it's not identical to that of previous version
|
||||
CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987",
|
||||
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null,
|
||||
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", new MeterDistance(5.05)), /* timeOnTimeFactor */ null,
|
||||
/* timeOnDistanceAllowancePerNauticalMile */ null, null);
|
||||
newVersion.setSuppressed(newVersion.competitors.get(13), true); // suppress an existing competitor; compaction should reduce this to a single number only
|
||||
newVersion.setSuppressed(somebodyNew, true); // check that mixed mode with existing and new competitors works as well
|
||||
@@ -278,7 +279,7 @@ public class LeaderboardDTODiffingTest {
|
||||
public void testDisplayNameChange() {
|
||||
newVersion.competitors = new ArrayList<CompetitorDTO>(newVersion.competitors); // clone competitor list so it's not identical to that of previous version
|
||||
CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987",
|
||||
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null,
|
||||
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", new MeterDistance(5.05)), /* timeOnTimeFactor */ null,
|
||||
/* timeOnDistanceAllowancePerNauticalMile */ null, null);
|
||||
newVersion.competitors.add(somebodyNew);
|
||||
newVersion.competitorDisplayNames = new HashMap<CompetitorDTO, String>(newVersion.competitorDisplayNames);
|
||||
@@ -308,7 +309,7 @@ public class LeaderboardDTODiffingTest {
|
||||
newVersion.setCompetitorsFromBestToWorst(r9, newOrdering);
|
||||
newVersion.competitors = new ArrayList<CompetitorDTO>(newVersion.competitors); // clone competitor list so it's not identical to that of previous version
|
||||
CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987",
|
||||
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null,
|
||||
/* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", new MeterDistance(5.05)), /* timeOnTimeFactor */ null,
|
||||
/* timeOnDistanceAllowancePerNauticalMile */ null, null);
|
||||
newVersion.competitors.add(somebodyNew);
|
||||
newOrdering.add(somebodyNew);
|
||||
|
||||
+2
-2
@@ -10,7 +10,6 @@ import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -30,6 +29,7 @@ import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tractracadapter.ReceiverType;
|
||||
import com.sap.sailing.domain.tractracadapter.TracTracConnectionConstants;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.util.ThreadPoolUtil;
|
||||
import com.tractrac.model.lib.api.event.CreateModelException;
|
||||
import com.tractrac.subscription.lib.api.SubscriberInitializationException;
|
||||
|
||||
@@ -77,7 +77,7 @@ public class ConcurrencyTest extends OnlineTracTracBasedTest {
|
||||
logger.info("1 thread: "+duration+"ns");
|
||||
logger.info("number of approximation points: "+approximation1.size());
|
||||
|
||||
dp = new DouglasPeucker<Competitor, GPSFixMoving>(teamAquaTrack, Executors.newFixedThreadPool(numberOfCPUs));
|
||||
dp = new DouglasPeucker<Competitor, GPSFixMoving>(teamAquaTrack, ThreadPoolUtil.INSTANCE.getDefaultBackgroundTaskThreadPoolExecutor());
|
||||
start = System.nanoTime();
|
||||
List<GPSFixMoving> approximation2 = dp.approximate(new MeterDistance(3), firstMarkPassing.getTimePoint(), lastMarkPassing.getTimePoint());
|
||||
duration = System.nanoTime()-start;
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.MeterDistance;
|
||||
import com.sap.sailing.domain.common.impl.NauticalMileDistance;
|
||||
import com.sap.sailing.domain.common.tracking.impl.CompactGPSFixImpl;
|
||||
import com.sap.sailing.domain.common.tracking.impl.CompactGPSFixMovingImpl;
|
||||
@@ -67,6 +68,12 @@ public class PositionTest {
|
||||
assertEquals(20004, Math.abs(southPole.getDistance(northPole).getKilometers()), 0.0001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void radTest() {
|
||||
assertEquals(180, new MeterDistance(20005000).getCentralAngleDeg(), 0.01);
|
||||
assertEquals(Math.PI, new MeterDistance(20005000).getCentralAngleRad(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bearingTest() {
|
||||
// Note that the bearing is a bearing on a great circle!
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package com.sap.sailing.domain.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogImpl;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
|
||||
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
|
||||
import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier;
|
||||
import com.sap.sailing.domain.regattalog.RegattaLogStore;
|
||||
import com.sap.sailing.domain.test.mock.MockedTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class RegattaLogAttachOnTrackedRaceTest {
|
||||
|
||||
private class MyMockedRegattaLogStore implements RegattaLogStore {
|
||||
private Map<RegattaLikeIdentifier, RegattaLog> regattaLogs = new HashMap<>();
|
||||
@Override
|
||||
public RegattaLog getRegattaLog(RegattaLikeIdentifier regattaLikeId, boolean ignoreCache) {
|
||||
if(!regattaLogs.containsKey(regattaLikeId)) {
|
||||
regattaLogs.put(regattaLikeId, new RegattaLogImpl(regattaLikeId));
|
||||
}
|
||||
return regattaLogs.get(regattaLikeId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRegattaLog(RegattaLikeIdentifier regattaLikeId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addImportedRegattaLog(RegattaLog regattaLog, RegattaLikeIdentifier identifier) {
|
||||
}
|
||||
}
|
||||
|
||||
private class MyMockedTrackedRace extends MockedTrackedRace {
|
||||
private static final long serialVersionUID = -5450144964435682919L;
|
||||
|
||||
private RegattaLog regattaLog;
|
||||
@Override
|
||||
public void attachRegattaLog(RegattaLog regattaLog) {
|
||||
this.regattaLog = regattaLog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<RegattaLog> getAttachedRegattaLogs() {
|
||||
return Collections.singletonList(regattaLog);
|
||||
}
|
||||
}
|
||||
|
||||
private FlexibleLeaderboard leaderboard;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
leaderboard = new FlexibleLeaderboardImpl(EmptyRaceLogStore.INSTANCE, new MyMockedRegattaLogStore(), "", null, new LowPoint(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachRegattaLogIsCalledWhenTrackedRaceIsSetToARaceColumn() {
|
||||
RaceColumn column = leaderboard.addRaceColumn("R1", false);
|
||||
TrackedRace trackedRace = new MyMockedTrackedRace();
|
||||
Fleet defaultFleet = Util.get(column.getFleets(), 0);
|
||||
column.setTrackedRace(defaultFleet, trackedRace);
|
||||
assertEquals(1, Util.size(trackedRace.getAttachedRegattaLogs()));
|
||||
assertSame(leaderboard.getRegattaLog(), Util.get(trackedRace.getAttachedRegattaLogs(), 0));
|
||||
}
|
||||
|
||||
}
|
||||
+4
-1
@@ -11,6 +11,7 @@ import java.util.Collections;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Matchers;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
@@ -27,6 +28,7 @@ import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl;
|
||||
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
|
||||
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.LineDetails;
|
||||
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicGPSFixTrackImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.TrackedLegImpl;
|
||||
@@ -137,7 +139,6 @@ public class StarbordSideOfStartLineRecognitionTest {
|
||||
Position startStarboardPosition = new DegreePosition(0, 1);
|
||||
Position windwardPosition = new DegreePosition(10, 0.5);
|
||||
MockedTrackedRaceImpl trackedRace = createTrackedRaceWithMarkPositions(startPortPosition, startStarboardPosition, windwardPosition);
|
||||
|
||||
Position p = trackedRace.getOrCreateTrack(trackedRace.getStartLine(now).getStarboardMarkWhileApproachingLine()).
|
||||
getEstimatedPosition(now, /* extrapolate */ false);
|
||||
assertEquals(startStarboardPosition, p);
|
||||
@@ -184,6 +185,8 @@ public class StarbordSideOfStartLineRecognitionTest {
|
||||
when(trackedRace.getTrackedLeg(course.getFirstLeg())).thenReturn(trackedLeg);
|
||||
when(trackedRace.getApproximatePosition(startWaypoint, now)).thenCallRealMethod();
|
||||
when(trackedRace.getApproximatePosition(windwardWaypoint, now)).thenCallRealMethod();
|
||||
when(trackedRace.getApproximatePosition(Matchers.eq(startWaypoint), Matchers.eq(now), Matchers.any(MarkPositionAtTimePointCache.class))).thenCallRealMethod();
|
||||
when(trackedRace.getApproximatePosition(Matchers.eq(windwardWaypoint), Matchers.eq(now), Matchers.any(MarkPositionAtTimePointCache.class))).thenCallRealMethod();
|
||||
return trackedRace;
|
||||
}
|
||||
|
||||
|
||||
+13
-11
@@ -37,8 +37,10 @@ import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.WindImpl;
|
||||
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||
import com.sap.sailing.domain.polars.PolarDataService;
|
||||
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.MarkPositionAtTimePointCacheImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.TrackedLegImpl;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
@@ -87,9 +89,8 @@ public class TargetTimeEstimationTest {
|
||||
TrackedLeg trackedLeg = new TrackedLegImpl(trackedRace, leg, competitors);
|
||||
|
||||
//Actual test of functionality
|
||||
Duration duration = trackedLeg.getEstimatedTimeToComplete(mockedPolars, timepoint);
|
||||
Duration duration = trackedLeg.getEstimatedTimeToComplete(mockedPolars, timepoint, new MarkPositionAtTimePointCacheImpl(trackedRace, timepoint));
|
||||
assertEquals(75494, duration.asMillis(), 100);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -123,9 +124,10 @@ public class TargetTimeEstimationTest {
|
||||
when(leg.getFrom()).thenReturn(from);
|
||||
when(leg.getTo()).thenReturn(to);
|
||||
|
||||
when(trackedRace.getApproximatePosition(from, timepoint)).thenReturn(startOfLeg);
|
||||
when(trackedRace.getApproximatePosition(to, timepoint)).thenReturn(endOfLeg);
|
||||
|
||||
when(trackedRace.getApproximatePosition(eq(from), eq(timepoint))).thenReturn(startOfLeg);
|
||||
when(trackedRace.getApproximatePosition(eq(to), eq(timepoint))).thenReturn(endOfLeg);
|
||||
when(trackedRace.getApproximatePosition(eq(from), eq(timepoint), any(MarkPositionAtTimePointCache.class))).thenReturn(startOfLeg);
|
||||
when(trackedRace.getApproximatePosition(eq(to), eq(timepoint), any(MarkPositionAtTimePointCache.class))).thenReturn(endOfLeg);
|
||||
|
||||
SpeedWithBearing speedWithBearingPort = new KnotSpeedWithBearingImpl(6, new DegreeBearingImpl(-45));
|
||||
SpeedWithBearingWithConfidence<Void> boatSpeedWithBearingWithConfidencePort = new SpeedWithBearingWithConfidenceImpl<Void>(speedWithBearingPort, 1, null);
|
||||
@@ -139,9 +141,8 @@ public class TargetTimeEstimationTest {
|
||||
TrackedLeg trackedLeg = new TrackedLegImpl(trackedRace, leg, competitors);
|
||||
|
||||
//Actual test of functionality
|
||||
Duration duration = trackedLeg.getEstimatedTimeToComplete(mockedPolars, timepoint);
|
||||
Duration duration = trackedLeg.getEstimatedTimeToComplete(mockedPolars, timepoint, new MarkPositionAtTimePointCacheImpl(trackedRace, timepoint));
|
||||
assertEquals(213513, duration.asMillis(), 100);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -175,9 +176,10 @@ public class TargetTimeEstimationTest {
|
||||
when(leg.getFrom()).thenReturn(from);
|
||||
when(leg.getTo()).thenReturn(to);
|
||||
|
||||
when(trackedRace.getApproximatePosition(from, timepoint)).thenReturn(startOfLeg);
|
||||
when(trackedRace.getApproximatePosition(to, timepoint)).thenReturn(endOfLeg);
|
||||
|
||||
when(trackedRace.getApproximatePosition(eq(from), eq(timepoint))).thenReturn(startOfLeg);
|
||||
when(trackedRace.getApproximatePosition(eq(to), eq(timepoint))).thenReturn(endOfLeg);
|
||||
when(trackedRace.getApproximatePosition(eq(from), eq(timepoint), any(MarkPositionAtTimePointCache.class))).thenReturn(startOfLeg);
|
||||
when(trackedRace.getApproximatePosition(eq(to), eq(timepoint), any(MarkPositionAtTimePointCache.class))).thenReturn(endOfLeg);
|
||||
|
||||
SpeedWithBearing speedWithBearingPort = new KnotSpeedWithBearingImpl(11, new DegreeBearingImpl(150));
|
||||
SpeedWithBearingWithConfidence<Void> boatSpeedWithBearingWithConfidencePort = new SpeedWithBearingWithConfidenceImpl<Void>(speedWithBearingPort, 1, null);
|
||||
@@ -191,7 +193,7 @@ public class TargetTimeEstimationTest {
|
||||
TrackedLeg trackedLeg = new TrackedLegImpl(trackedRace, leg, competitors);
|
||||
|
||||
//Actual test of functionality
|
||||
Duration duration = trackedLeg.getEstimatedTimeToComplete(mockedPolars, timepoint);
|
||||
Duration duration = trackedLeg.getEstimatedTimeToComplete(mockedPolars, timepoint, new MarkPositionAtTimePointCacheImpl(trackedRace, timepoint));
|
||||
assertEquals(95090, duration.asMillis(), 100);
|
||||
|
||||
}
|
||||
|
||||
@@ -374,6 +374,27 @@ public class TrackTest {
|
||||
getB().getKnots(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxSpeedForFixOverwrittenWithLowerSpeed() {
|
||||
DynamicGPSFixMovingTrackImpl<Object> track = new DynamicGPSFixMovingTrackImpl<Object>(new Object(), /* millisecondsOverWhichToAverage */ 30000l);
|
||||
GPSFixMoving slow = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl(
|
||||
1, new DegreeBearingImpl(123)));
|
||||
GPSFixMoving fast = new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(3600000), new KnotSpeedWithBearingImpl(
|
||||
2, new DegreeBearingImpl(123)));
|
||||
track.addGPSFix(fast);
|
||||
assertEquals(2., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)).
|
||||
getB().getKnots(), 0.001);
|
||||
track.addGPSFix(slow);
|
||||
track.lockForRead();
|
||||
try {
|
||||
assertEquals(1, track.getFixes().size());
|
||||
} finally {
|
||||
track.unlockAfterRead();
|
||||
}
|
||||
assertEquals(1., track.getMaximumSpeedOverGround(new MillisecondsTimePoint(0), new MillisecondsTimePoint(10800000)).
|
||||
getB().getKnots(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxSpeedForMovingTrackWithFixAtIntervalBoundaryAfterQuery() {
|
||||
DynamicGPSFixMovingTrackImpl<Object> track = new DynamicGPSFixMovingTrackImpl<Object>(new Object(), /* millisecondsOverWhichToAverage */ 30000l);
|
||||
|
||||
+2
@@ -22,6 +22,7 @@ import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl;
|
||||
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicGPSFixTrackImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
|
||||
@@ -50,6 +51,7 @@ public class TrackedRaceCenterTest {
|
||||
trackedRace = mock(DynamicTrackedRaceImpl.class);
|
||||
when(trackedRace.getCenterOfCourse(Matchers.any(TimePoint.class))).thenCallRealMethod();
|
||||
when(trackedRace.getApproximatePosition(Matchers.any(Waypoint.class), Matchers.any(TimePoint.class))).thenCallRealMethod();
|
||||
when(trackedRace.getApproximatePosition(Matchers.any(Waypoint.class), Matchers.any(TimePoint.class), Matchers.any(MarkPositionAtTimePointCache.class))).thenCallRealMethod();
|
||||
RaceDefinition race = mock(RaceDefinition.class);
|
||||
when(trackedRace.getRace()).thenReturn(race);
|
||||
course = mock(Course.class);
|
||||
|
||||
+11
-1
@@ -63,6 +63,7 @@ import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.LineDetails;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
|
||||
import com.sap.sailing.domain.tracking.RaceAbortedListener;
|
||||
import com.sap.sailing.domain.tracking.RaceChangeListener;
|
||||
import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider;
|
||||
@@ -446,6 +447,15 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getBuoyZoneRadiusInHullLengths(){
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBuoyZoneRadiusInHullLengths(Double buoyZoneRadiusInHullLengths){
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegattaLikeIdentifier getRegattaLikeIdentifier() {
|
||||
return null;
|
||||
@@ -612,7 +622,7 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint) {
|
||||
public Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint, MarkPositionAtTimePointCache markPositionCache) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -42,6 +42,7 @@ import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.LineDetails;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
|
||||
import com.sap.sailing.domain.tracking.RaceAbortedListener;
|
||||
import com.sap.sailing.domain.tracking.RaceChangeListener;
|
||||
import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider;
|
||||
@@ -218,7 +219,7 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint) {
|
||||
public Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint, MarkPositionAtTimePointCache markPositionCache) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ public class BravoFixTrackSerializationTest {
|
||||
}
|
||||
|
||||
private void addOrReplaceBravoFixToTrack(boolean replace) {
|
||||
double[] fixData = new double[BravoSensorDataMetadata.INSTANCE.getColumns().size()];
|
||||
double[] fixData = new double[BravoSensorDataMetadata.INSTANCE.columnCount];
|
||||
fixData[BravoSensorDataMetadata.INSTANCE.rideHeightColumn] = rideHeight;
|
||||
track.add(new BravoFixImpl(new DoubleVectorFixImpl(timePoint, fixData)), replace);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@ import com.sap.sse.common.TimePoint;
|
||||
*
|
||||
*/
|
||||
public interface Regatta extends NamedWithID, IsRegattaLike, HasRaceColumnsAndRegattaLike {
|
||||
|
||||
public static final double DEFAULT_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS = 2;
|
||||
|
||||
ScoringScheme getScoringScheme();
|
||||
|
||||
/**
|
||||
@@ -155,6 +158,14 @@ public interface Regatta extends NamedWithID, IsRegattaLike, HasRaceColumnsAndRe
|
||||
|
||||
RegattaAndRaceIdentifier getRaceIdentifier(RaceDefinition race);
|
||||
|
||||
/**
|
||||
* Define the value which would be multipled by hull length from {@link BoatClass}.
|
||||
* Next the calculated value {@link RegattaUtil} would be used to fill out radius of buoy on race map setting.
|
||||
*/
|
||||
public Double getBuoyZoneRadiusInHullLengths();
|
||||
|
||||
public void setBuoyZoneRadiusInHullLengths(Double buoyZoneRadiusInHullLengths);
|
||||
|
||||
/**
|
||||
* When there is no race committee app in place and no operator is managing the race start times for this regatta,
|
||||
* start times can optionally be inferred from the start mark passings by the {@link TrackedRace}s in this regatta.
|
||||
|
||||
+8
-2
@@ -43,6 +43,10 @@ public abstract class AbstractRaceExecutionOrderProvider implements RaceExecutio
|
||||
|
||||
protected abstract Map<Fleet, Iterable<? extends RaceColumn>> getRaceColumnsOfSeries();
|
||||
|
||||
/**
|
||||
* For all tracked races found on any of the {@link #getRaceColumnsOfSeries() race columns} produces a valid and
|
||||
* potentially empty set.
|
||||
*/
|
||||
private Map<TrackedRace, Set<TrackedRace>> reloadAndGetPreviousRacesByRace() {
|
||||
final Map<TrackedRace, Set<TrackedRace>> previousRacesByRace = new HashMap<>();
|
||||
for (Entry<Fleet, Iterable<? extends RaceColumn>> raceColumnsInSeries : getRaceColumnsOfSeries().entrySet()) {
|
||||
@@ -96,11 +100,13 @@ public abstract class AbstractRaceExecutionOrderProvider implements RaceExecutio
|
||||
|
||||
@Override
|
||||
public Set<TrackedRace> getPreviousRacesInExecutionOrder(TrackedRace race) {
|
||||
Set<TrackedRace> result = Collections.emptySet();
|
||||
final Set<TrackedRace> result;
|
||||
final Map<TrackedRace, Set<TrackedRace>> previousRacesByRace = getPreviousRacesByRace();
|
||||
if (previousRacesByRace != null) {
|
||||
result = previousRacesByRace.get(race);
|
||||
}
|
||||
} else {
|
||||
result = Collections.emptySet();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+5
-15
@@ -6,12 +6,9 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.RunnableFuture;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
@@ -31,7 +28,7 @@ import com.sap.sse.common.Util;
|
||||
public class DouglasPeucker<ItemType, FixType extends GPSFix> {
|
||||
private final GPSFixTrack<ItemType, FixType> track;
|
||||
|
||||
private final Executor executor;
|
||||
private final ScheduledExecutorService executor;
|
||||
|
||||
public DouglasPeucker(GPSFixTrack<ItemType, FixType> track) {
|
||||
this.track = track;
|
||||
@@ -42,7 +39,7 @@ public class DouglasPeucker<ItemType, FixType extends GPSFix> {
|
||||
* Allows clients to specify a non-default, optionally multi-threaded executor that will be used to perform the
|
||||
* high-effort computations.
|
||||
*/
|
||||
public DouglasPeucker(GPSFixTrack<ItemType, FixType> track, Executor executor) {
|
||||
public DouglasPeucker(GPSFixTrack<ItemType, FixType> track, ScheduledExecutorService executor) {
|
||||
this.track = track;
|
||||
this.executor = executor;
|
||||
}
|
||||
@@ -96,15 +93,8 @@ public class DouglasPeucker<ItemType, FixType extends GPSFix> {
|
||||
if (fix.getTimePoint().compareTo(to) > 0) {
|
||||
break;
|
||||
}
|
||||
RunnableFuture<Util.Pair<FixType, Distance>> crossTrackErrorFuture = new FutureTask<Util.Pair<FixType, Distance>>(
|
||||
new Callable<Util.Pair<FixType, Distance>>() {
|
||||
@Override
|
||||
public Util.Pair<FixType, Distance> call() throws Exception {
|
||||
return new Util.Pair<FixType, Distance>(fix, fix.getPosition().absoluteCrossTrackError(
|
||||
fromPosition, bearing));
|
||||
}
|
||||
});
|
||||
executor.execute(crossTrackErrorFuture);
|
||||
Future<Util.Pair<FixType, Distance>> crossTrackErrorFuture = executor.submit(
|
||||
()->new Util.Pair<FixType, Distance>(fix, fix.getPosition().absoluteCrossTrackError(fromPosition, bearing)));
|
||||
crossTrackErrorFutures.add(crossTrackErrorFuture);
|
||||
}
|
||||
for (Future<Util.Pair<FixType, Distance>> crossTrackErrorFuture : crossTrackErrorFutures) {
|
||||
|
||||
@@ -115,6 +115,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
private transient RaceLogStore raceLogStore;
|
||||
private final IsRegattaLike regattaLikeHelper;
|
||||
private final RankingMetricConstructor rankingMetricConstructor;
|
||||
private Double buoyZoneRadiusInHullLengths;
|
||||
|
||||
private CourseArea defaultCourseArea;
|
||||
private RegattaConfiguration configuration;
|
||||
@@ -162,7 +163,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
Iterable<? extends Series> series, boolean persistent, ScoringScheme scoringScheme, Serializable id,
|
||||
CourseArea courseArea, RankingMetricConstructor rankingMetricConstructor) {
|
||||
this(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, name, boatClass, startDate, endDate, series,
|
||||
persistent, scoringScheme, id, courseArea, /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false,
|
||||
persistent, scoringScheme, id, courseArea, 0.0, /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false,
|
||||
rankingMetricConstructor);
|
||||
}
|
||||
|
||||
@@ -204,7 +205,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
/* isMedal */false, /* isFleetsCanRunInParallel */ true, Collections
|
||||
.singletonList(new FleetImpl(LeaderboardNameConstants.DEFAULT_FLEET_NAME)),
|
||||
/* race column names */new ArrayList<String>(), trackedRegattaRegistry)), /* persistent */false,
|
||||
scoringScheme, id, courseArea, /* useStartTimeInference */true, controlTrackingFromStartAndFinishTimes,
|
||||
scoringScheme, id, courseArea, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */true, controlTrackingFromStartAndFinishTimes,
|
||||
rankingMetricConstructor);
|
||||
}
|
||||
|
||||
@@ -215,7 +216,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
*/
|
||||
public <S extends Series> RegattaImpl(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, String name,
|
||||
BoatClass boatClass, TimePoint startDate, TimePoint endDate, Iterable<S> series, boolean persistent,
|
||||
ScoringScheme scoringScheme, Serializable id, CourseArea courseArea, boolean useStartTimeInference,
|
||||
ScoringScheme scoringScheme, Serializable id, CourseArea courseArea, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference,
|
||||
boolean controlTrackingFromStartAndFinishTimes, RankingMetricConstructor rankingMetricConstructor) {
|
||||
super(name);
|
||||
this.rankingMetricConstructor = rankingMetricConstructor;
|
||||
@@ -241,6 +242,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
this.scoringScheme = scoringScheme;
|
||||
this.defaultCourseArea = courseArea;
|
||||
this.configuration = null;
|
||||
this.buoyZoneRadiusInHullLengths = buoyZoneRadiusInHullLengths;
|
||||
this.regattaLikeHelper = new BaseRegattaLikeImpl(new RegattaAsRegattaLikeIdentifier(this), regattaLogStore) {
|
||||
private static final long serialVersionUID = 8546222568682770206L;
|
||||
|
||||
@@ -572,6 +574,16 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getBuoyZoneRadiusInHullLengths() {
|
||||
return buoyZoneRadiusInHullLengths;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBuoyZoneRadiusInHullLengths(Double buoyZoneRadiusInHullLengths) {
|
||||
this.buoyZoneRadiusInHullLengths = buoyZoneRadiusInHullLengths;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CourseArea getDefaultCourseArea() {
|
||||
return defaultCourseArea;
|
||||
|
||||
+11
-9
@@ -23,6 +23,7 @@ import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.concurrent.LockUtil;
|
||||
import com.sap.sse.concurrent.NamedReentrantReadWriteLock;
|
||||
import com.sap.sse.util.impl.FutureTaskWithTracingGet;
|
||||
|
||||
/**
|
||||
* Caches the expensive to compute {@link LeaderboardDTO} results of a
|
||||
@@ -140,15 +141,16 @@ public class LeaderboardDTOCache implements LeaderboardCache {
|
||||
LockUtil.unlockAfterRead(leaderboardCacheLock);
|
||||
}
|
||||
if (future == null) {
|
||||
future = new FutureTask<LeaderboardDTO>(new Callable<LeaderboardDTO>() {
|
||||
@Override
|
||||
public LeaderboardDTO call() throws Exception {
|
||||
LeaderboardDTO result = leaderboard.computeDTO(adjustedTimePoint,
|
||||
namesOfRaceColumnsForWhichToLoadLegDetails, addOverallDetails,
|
||||
waitForLatestAnalyses, trackedRegattaRegistry, baseDomainFactory, /* fillTotalPointsUncorrected */ false);
|
||||
return result;
|
||||
}
|
||||
});
|
||||
future = new FutureTaskWithTracingGet<LeaderboardDTO>(LeaderboardDTOCache.class.getName()+" for leaderboard "+leaderboard.getName(),
|
||||
new Callable<LeaderboardDTO>() {
|
||||
@Override
|
||||
public LeaderboardDTO call() throws Exception {
|
||||
LeaderboardDTO result = leaderboard.computeDTO(adjustedTimePoint,
|
||||
namesOfRaceColumnsForWhichToLoadLegDetails, addOverallDetails,
|
||||
waitForLatestAnalyses, trackedRegattaRegistry, baseDomainFactory, /* fillTotalPointsUncorrected */ false);
|
||||
return result;
|
||||
}
|
||||
});
|
||||
// The add(Leaderboard) method that the cache manager calls back on this class does nothing, so no synchronization required
|
||||
this.leaderboardCacheManager.add(leaderboard); // ensure the leaderboard is tracked for changes to invalidate
|
||||
LockUtil.lockForWrite(leaderboardCacheLock);
|
||||
|
||||
+8
-10
@@ -21,7 +21,6 @@ import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.RunnableFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@@ -97,6 +96,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.concurrent.LockUtil;
|
||||
import com.sap.sse.concurrent.NamedReentrantReadWriteLock;
|
||||
import com.sap.sse.util.ThreadPoolUtil;
|
||||
import com.sap.sse.util.impl.FutureTaskWithTracingGet;
|
||||
|
||||
/**
|
||||
* Base implementation for various types of leaderboards. The {@link RaceColumnListener} implementation forwards events
|
||||
@@ -311,7 +311,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
this.suppressedCompetitors = new HashSet<Competitor>();
|
||||
this.suppressedCompetitorsLock = new NamedReentrantReadWriteLock("suppressedCompetitorsLock", /* fair */ false);
|
||||
this.raceColumnListeners = new RaceColumnListeners();
|
||||
this.raceDetailsAtEndOfTrackingCache = new HashMap<com.sap.sse.common.Util.Pair<TrackedRace, Competitor>, RunnableFuture<RaceDetails>>();
|
||||
this.raceDetailsAtEndOfTrackingCache = new HashMap<>();
|
||||
initTransientFields();
|
||||
}
|
||||
|
||||
@@ -330,7 +330,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
}
|
||||
|
||||
private void initTransientFields() {
|
||||
this.raceDetailsAtEndOfTrackingCache = new HashMap<com.sap.sse.common.Util.Pair<TrackedRace,Competitor>, RunnableFuture<RaceDetails>>();
|
||||
this.raceDetailsAtEndOfTrackingCache = new HashMap<>();
|
||||
this.cacheInvalidationListeners = new HashSet<CacheInvalidationListener>();
|
||||
// When many updates are triggered in a short period of time by a single thread, ensure that the single thread
|
||||
// providing the updates is not outperformed by all the re-calculations happening here. Leave at least one
|
||||
@@ -1225,7 +1225,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
}
|
||||
// Now create the race columns and, as a future task, set their competitorsFromBestToWorst, then wait for all these
|
||||
// futures to finish:
|
||||
Map<RaceColumn, FutureTask<List<CompetitorDTO>>> competitorsFromBestToWorstTasks = new HashMap<>();
|
||||
Map<RaceColumn, Future<List<CompetitorDTO>>> competitorsFromBestToWorstTasks = new HashMap<>();
|
||||
for (final RaceColumn raceColumn : this.getRaceColumns()) {
|
||||
boolean isMetaLeaderboardColumn = raceColumn instanceof MetaLeaderboardColumn;
|
||||
RaceColumnDTO raceColumnDTO = result.createEmptyRaceColumn(raceColumn.getName(), raceColumn.isMedalRace(),
|
||||
@@ -1253,13 +1253,12 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
raceColumn instanceof RaceColumnInSeries ? ((RaceColumnInSeries) raceColumn).getSeries().getName() : null,
|
||||
fleetDTO, raceColumn.isMedalRace(), raceIdentifier, race, isMetaLeaderboardColumn);
|
||||
}
|
||||
FutureTask<List<CompetitorDTO>> task = new FutureTask<List<CompetitorDTO>>(
|
||||
Future<List<CompetitorDTO>> task = executor.submit(
|
||||
() -> baseDomainFactory.getCompetitorDTOList(AbstractSimpleLeaderboardImpl.this.getCompetitorsFromBestToWorst(raceColumn, timePoint)));
|
||||
executor.execute(task);
|
||||
competitorsFromBestToWorstTasks.put(raceColumn, task);
|
||||
}
|
||||
// wait for the competitor orderings to have been computed for all race columns before continuing; subsequent tasks may depend on these data
|
||||
for (Map.Entry<RaceColumn, FutureTask<List<CompetitorDTO>>> raceColumnAndTaskToJoin : competitorsFromBestToWorstTasks.entrySet()) {
|
||||
for (Map.Entry<RaceColumn, Future<List<CompetitorDTO>>> raceColumnAndTaskToJoin : competitorsFromBestToWorstTasks.entrySet()) {
|
||||
try {
|
||||
result.setCompetitorsFromBestToWorst(raceColumnAndTaskToJoin.getKey().getName(), raceColumnAndTaskToJoin.getValue().get());
|
||||
} catch (InterruptedException e) {
|
||||
@@ -1323,7 +1322,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
Map<String, Future<LeaderboardEntryDTO>> futuresForColumnName = new HashMap<String, Future<LeaderboardEntryDTO>>();
|
||||
final Set<RaceColumn> discardedRaceColumns = getResultDiscardingRule().getDiscardedRaceColumns(competitor, this, getRaceColumns(), timePoint);
|
||||
for (final RaceColumn raceColumn : this.getRaceColumns()) {
|
||||
RunnableFuture<LeaderboardEntryDTO> future = new FutureTask<LeaderboardEntryDTO>(() -> {
|
||||
Future<LeaderboardEntryDTO> future = executor.submit(() -> {
|
||||
Entry entry = AbstractSimpleLeaderboardImpl.this.getEntry(competitor, raceColumn, timePoint, discardedRaceColumns);
|
||||
return getLeaderboardEntryDTO(entry, raceColumn, competitor, timePoint,
|
||||
namesOfRaceColumnsForWhichToLoadLegDetails != null
|
||||
@@ -1331,7 +1330,6 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
.getName()), waitForLatestAnalyses, legRanksCache, baseDomainFactory,
|
||||
fillTotalPointsUncorrected, cache);
|
||||
});
|
||||
executor.execute(future);
|
||||
futuresForColumnName.put(raceColumn.getName(), future);
|
||||
}
|
||||
for (Map.Entry<String, Future<LeaderboardEntryDTO>> raceColumnNameAndFuture : futuresForColumnName.entrySet()) {
|
||||
@@ -1611,7 +1609,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
raceDetails = raceDetailsAtEndOfTrackingCache.get(key);
|
||||
if (raceDetails == null) {
|
||||
needToRunRaceDetails = true;
|
||||
raceDetails = new FutureTask<RaceDetails>(new Callable<RaceDetails>() {
|
||||
raceDetails = new FutureTaskWithTracingGet<RaceDetails>("RaceDetails for "+trackedRace, new Callable<RaceDetails>() {
|
||||
@Override
|
||||
public RaceDetails call() throws Exception {
|
||||
TimePoint end = trackedRace.getEndOfRace();
|
||||
|
||||
+38
-15
@@ -9,7 +9,6 @@ import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -173,7 +172,7 @@ public class MarkPassingCalculator {
|
||||
+ " while waiting for new GPSFixes");
|
||||
}
|
||||
listener.getQueue().drainTo(allNewFixInsertions);
|
||||
logger.finer("MPC for "+raceName+" recieved "+ allNewFixInsertions.size()+" new updates.");
|
||||
logger.fine("MPC for "+raceName+" received "+ allNewFixInsertions.size()+" new updates.");
|
||||
for (StorePositionUpdateStrategy fixInsertion : allNewFixInsertions) {
|
||||
if (listener.isEndMarker(fixInsertion)) {
|
||||
logger.info("Stopping "+MarkPassingCalculator.this+"'s listener for race "+raceName);
|
||||
@@ -212,8 +211,7 @@ public class MarkPassingCalculator {
|
||||
}
|
||||
executor.invokeAll(tasks);
|
||||
}
|
||||
updateManuallySetMarkPassings(fixedMarkPassings, removedFixedMarkPassings, suppressedMarkPassings,
|
||||
unsuppressedMarkPassings);
|
||||
updateManuallySetMarkPassings(fixedMarkPassings, removedFixedMarkPassings, suppressedMarkPassings, unsuppressedMarkPassings);
|
||||
computeMarkPasses(competitorFixes, markFixes);
|
||||
competitorFixes.clear();
|
||||
markFixes.clear();
|
||||
@@ -284,9 +282,24 @@ public class MarkPassingCalculator {
|
||||
fixes.addAll(fixesAffectedByNewMarkFixes.getValue());
|
||||
}
|
||||
}
|
||||
List<Callable<Object>> tasks = new ArrayList<>();
|
||||
for (Entry<Competitor, Set<GPSFix>> c : combinedCompetitorFixes.entrySet()) {
|
||||
tasks.add(Executors.callable(new ComputeMarkPassings(c.getKey(), c.getValue())));
|
||||
List<Callable<Void>> tasks = new ArrayList<>();
|
||||
for (final Entry<Competitor, Set<GPSFix>> c : combinedCompetitorFixes.entrySet()) {
|
||||
final Runnable runnable = new ComputeMarkPassings(c.getKey(), c.getValue());
|
||||
tasks.add(new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
runnable.run();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A reasonable toString implementation helps identifying these tasks in log messages for long-running tasks
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Mark passing calculation for competitor "+c.getKey()+" with "+c.getValue().size()+" fixes";
|
||||
}
|
||||
});
|
||||
}
|
||||
try {
|
||||
executor.invokeAll(tasks);
|
||||
@@ -296,8 +309,8 @@ public class MarkPassingCalculator {
|
||||
}
|
||||
|
||||
private class ComputeMarkPassings implements Runnable {
|
||||
Competitor c;
|
||||
Iterable<GPSFix> fixes;
|
||||
final Competitor c;
|
||||
final Iterable<GPSFix> fixes;
|
||||
|
||||
public ComputeMarkPassings(Competitor c, Iterable<GPSFix> fixes) {
|
||||
this.c = c;
|
||||
@@ -306,12 +319,22 @@ public class MarkPassingCalculator {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
logger.finer("Calculating MarkPassings for race "+raceName+", competitor " + c + " (" + Util.size(fixes) + " new fixes)");
|
||||
Util.Pair<Iterable<Candidate>, Iterable<Candidate>> candidateDeltas = finder.getCandidateDeltas(c, fixes);
|
||||
logger.finer("Received " + Util.size(candidateDeltas.getA()) + " new Candidates for race "+raceName+
|
||||
" and competitor "+c+" and will remove "
|
||||
+ Util.size(candidateDeltas.getB()) + " old Candidates for " + c);
|
||||
chooser.calculateMarkPassDeltas(c, candidateDeltas.getA(), candidateDeltas.getB());
|
||||
try {
|
||||
if (logger.isLoggable(Level.FINER)) {
|
||||
logger.finer("Calculating MarkPassings for race "+raceName+", competitor " + c + " (" + Util.size(fixes) + " new fixes)");
|
||||
}
|
||||
Util.Pair<Iterable<Candidate>, Iterable<Candidate>> candidateDeltas = finder.getCandidateDeltas(c, fixes);
|
||||
if (logger.isLoggable(Level.FINER)) {
|
||||
logger.finer("Received " + Util.size(candidateDeltas.getA()) + " new Candidates for race "+raceName+
|
||||
" and competitor "+c+" and will remove "
|
||||
+ Util.size(candidateDeltas.getB()) + " old Candidates for " + c);
|
||||
}
|
||||
chooser.calculateMarkPassDeltas(c, candidateDeltas.getA(), candidateDeltas.getB());
|
||||
} catch (Exception e) {
|
||||
// make sure the exception is logged and not only "swallowed" and suppressed by an invokeAll(...) statement
|
||||
logger.log(Level.SEVERE, "Exception trying to compute mark passings for competitor "+c, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+116
-96
@@ -39,6 +39,8 @@ import com.sap.sailing.domain.markpassingcalculation.CandidateFinder;
|
||||
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
|
||||
import com.sap.sailing.domain.tracking.impl.MarkPositionAtTimePointCacheImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.TimedComparator;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
@@ -47,6 +49,7 @@ import com.sap.sse.common.Timed;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.impl.TimeRangeImpl;
|
||||
import com.sap.sse.concurrent.LockUtil;
|
||||
import com.sap.sse.util.ThreadPoolUtil;
|
||||
|
||||
/**
|
||||
@@ -383,24 +386,30 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
changedWaypoints.add(w);
|
||||
}
|
||||
}
|
||||
final Set<Callable<Void>> tasks = new HashSet<>();;
|
||||
final Set<Callable<Void>> tasks = new HashSet<>();
|
||||
final Thread executingThread = Thread.currentThread(); // most likely the MarkPassingCalculator.Listen thread
|
||||
for (Competitor c : race.getRace().getCompetitors()) {
|
||||
tasks.add(()->{
|
||||
List<Candidate> badCans = new ArrayList<>();
|
||||
List<Candidate> newCans = new ArrayList<>();
|
||||
for (Waypoint w : changedWaypoints) {
|
||||
Map<List<GPSFix>, Candidate> xteCans = getXteCandidates(c, w);
|
||||
badCans.addAll(xteCans.values());
|
||||
xteCans.clear();
|
||||
Map<GPSFix, Candidate> distanceCans = getDistanceCandidates(c, w);
|
||||
badCans.addAll(distanceCans.values());
|
||||
distanceCans.clear();
|
||||
LockUtil.propagateLockSetFrom(executingThread); // "inherit" the course read lock from the "calling" thread into the thread pool executor thread
|
||||
try {
|
||||
List<Candidate> badCans = new ArrayList<>();
|
||||
List<Candidate> newCans = new ArrayList<>();
|
||||
for (Waypoint w : changedWaypoints) {
|
||||
Map<List<GPSFix>, Candidate> xteCans = getXteCandidates(c, w);
|
||||
badCans.addAll(xteCans.values());
|
||||
xteCans.clear();
|
||||
Map<GPSFix, Candidate> distanceCans = getDistanceCandidates(c, w);
|
||||
badCans.addAll(distanceCans.values());
|
||||
distanceCans.clear();
|
||||
}
|
||||
Set<GPSFix> allFixes = getAllFixes(c);
|
||||
newCans.addAll(checkForDistanceCandidateChanges(c, allFixes, changedWaypoints).getA());
|
||||
newCans.addAll(checkForXTECandidatesChanges(c, allFixes, changedWaypoints).getA());
|
||||
result.put(c, new Util.Pair<List<Candidate>, List<Candidate>>(newCans, badCans));
|
||||
return null;
|
||||
} finally {
|
||||
LockUtil.unpropagateLockSetFrom(executingThread); // "return" the course read lock from the thread pool executor thread to the "calling" thread
|
||||
}
|
||||
Set<GPSFix> allFixes = getAllFixes(c);
|
||||
newCans.addAll(checkForDistanceCandidateChanges(c, allFixes, changedWaypoints).getA());
|
||||
newCans.addAll(checkForXTECandidatesChanges(c, allFixes, changedWaypoints).getA());
|
||||
result.put(c, new Util.Pair<List<Candidate>, List<Candidate>>(newCans, badCans));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
executor.invokeAll(tasks);
|
||||
@@ -513,8 +522,8 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
private Set<GPSFix> getAllFixes(Competitor c) {
|
||||
Set<GPSFix> fixes = new TreeSet<GPSFix>(comp);
|
||||
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = race.getTrack(c);
|
||||
track.lockForRead();
|
||||
try {
|
||||
track.lockForRead();
|
||||
for (GPSFix fix : track.getFixes(
|
||||
timeRangeForValidCandidates.from(), /* fromInclusive */ true,
|
||||
timeRangeForValidCandidates.to(), /* toInclusive */ true)) {
|
||||
@@ -542,8 +551,8 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
affectedFixes.add(fix);
|
||||
GPSFix fixBefore;
|
||||
GPSFix fixAfter;
|
||||
track.lockForRead();
|
||||
try {
|
||||
track.lockForRead();
|
||||
TimePoint timePoint = fix.getTimePoint();
|
||||
fixBefore = track.getLastFixBefore(timePoint);
|
||||
fixAfter = track.getFirstFixAfter(timePoint);
|
||||
@@ -604,15 +613,16 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
if (Math.abs(dis.getMeters()) < Math.abs(disBefore.getMeters())
|
||||
&& Math.abs(dis.getMeters()) < Math.abs(disAfter.getMeters())) {
|
||||
t = fix.getTimePoint();
|
||||
final MarkPositionAtTimePointCache markPositionCache = new MarkPositionAtTimePointCacheImpl(race, t);
|
||||
p = fix.getPosition();
|
||||
Double newProbability = getDistanceBasedProbability(w, t, dis);
|
||||
Double newProbability = getDistanceBasedProbability(w, t, dis, markPositionCache);
|
||||
if (newProbability != null) {
|
||||
// FIXME why not generate the candidate here where we have all information at hand?
|
||||
final double newOnCorrectSideOfWaypointPenalty = getSidePenalty(w, p, t, portMark);
|
||||
final double newOnCorrectSideOfWaypointPenalty = getSidePenalty(w, p, t, portMark, markPositionCache);
|
||||
newProbability *= newOnCorrectSideOfWaypointPenalty * PENALTY_FOR_DISTANCE_CANDIDATES;
|
||||
final Double newStartProbabilityBasedOnOtherCompetitors;
|
||||
if (isStartWaypoint(w)) {
|
||||
newStartProbabilityBasedOnOtherCompetitors = getProbabilityForStartCandidateBasedOnOtherCompetitorsBehavior(c, t);
|
||||
newStartProbabilityBasedOnOtherCompetitors = getProbabilityForStartCandidateBasedOnOtherCompetitorsBehavior(c, t, markPositionCache);
|
||||
if (newStartProbabilityBasedOnOtherCompetitors != null) {
|
||||
newProbability *= newStartProbabilityBasedOnOtherCompetitors;
|
||||
}
|
||||
@@ -663,6 +673,7 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
private Map<Waypoint, List<Distance>> getDistances(Competitor c, GPSFix fix) {
|
||||
// TODO Possibly for specific waypoints
|
||||
Map<Waypoint, List<Distance>> result = distanceCache.get(c).get(fix);
|
||||
final MarkPositionAtTimePointCache markPositionCache = new MarkPositionAtTimePointCacheImpl(race, fix.getTimePoint());
|
||||
if (result == null) {
|
||||
// Else calculate distances and put them into the cache
|
||||
result = new LinkedHashMap<>();
|
||||
@@ -670,7 +681,7 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
course.lockForRead();
|
||||
try {
|
||||
for (Waypoint w : course.getWaypoints()) {
|
||||
List<Distance> distances = calculateDistance(fix.getPosition(), w, fix.getTimePoint());
|
||||
List<Distance> distances = calculateDistance(fix.getPosition(), w, fix.getTimePoint(), markPositionCache);
|
||||
result.put(w, distances);
|
||||
}
|
||||
} finally {
|
||||
@@ -811,13 +822,14 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
result = new HashMap<>();
|
||||
Position p = fix.getPosition();
|
||||
TimePoint t = fix.getTimePoint();
|
||||
final MarkPositionAtTimePointCache markPositionCache = new MarkPositionAtTimePointCacheImpl(race, t);
|
||||
Course course = race.getRace().getCourse();
|
||||
course.lockForRead();
|
||||
try {
|
||||
for (Waypoint w : course.getWaypoints()) {
|
||||
List<Distance> distances = new ArrayList<>();
|
||||
result.put(w, distances);
|
||||
for (Util.Pair<Position, Bearing> crossingInfo : getCrossingInformation(w, t)) {
|
||||
for (Util.Pair<Position, Bearing> crossingInfo : getCrossingInformation(w, t, markPositionCache)) {
|
||||
if (crossingInfo.getA() != null && crossingInfo.getB() != null) {
|
||||
distances.add(p.crossTrackError(crossingInfo.getA(), crossingInfo.getB()));
|
||||
}
|
||||
@@ -831,20 +843,6 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the cross-track error of each fix to the position and crossing bearing of each waypoint. Gates have
|
||||
* two of these and lines always go from the port mark to the starboard mark.
|
||||
*
|
||||
*
|
||||
* /* private void calculateCrossTrackErrors(Competitor c, Iterable<GPSFix> fixes, Iterable<Waypoint>
|
||||
* waypointsToCalculate) { for (GPSFix fix : fixes) { Position fixPos = fix.getPosition(); TimePoint t =
|
||||
* fix.getTimePoint(); Map<Waypoint, List<Double>> waypointXTE = new HashMap<Waypoint, List<Double>>();
|
||||
* crossTrackErrors.get(c).put(fix, waypointXTE); for (Waypoint w : race.getRace().getCourse().getWaypoints()) {
|
||||
* List<Double> xte = new ArrayList<>(); waypointXTE.put(w, xte); for (Util.Pair<Position, Bearing> crossingInfo :
|
||||
* getCrossingInformation(w, t)) { xte.add(fixPos.crossTrackError(crossingInfo.getA(),
|
||||
* crossingInfo.getB()).getMeters()); } } } }
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@code xte1} and {@code xte2} are expected to have different signums or both be 0. The method
|
||||
* interpolates between the time points {@code t1} and {@code t2} according to where the XTE is
|
||||
@@ -856,10 +854,11 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
final double ratio = (Math.abs(xte1) / (Math.abs(xte1) + Math.abs(xte2)));
|
||||
final TimePoint t = t1.plus((long) (differenceInMillis * ratio));
|
||||
final Position p = race.getTrack(c).getEstimatedPosition(t, false);
|
||||
final List<Distance> distances = calculateDistance(p, w, t);
|
||||
final List<Distance> distances = calculateDistance(p, w, t, new MarkPositionAtTimePointCacheImpl(race, t));
|
||||
final Distance d = portMark ? distances.get(0) : distances.get(1);
|
||||
final double sidePenalty = getSidePenalty(w, p, t, portMark);
|
||||
double probability = getDistanceBasedProbability(w, t, d) * sidePenalty;
|
||||
final MarkPositionAtTimePointCache markPositionCache = new MarkPositionAtTimePointCacheImpl(race, t);
|
||||
final double sidePenalty = getSidePenalty(w, p, t, portMark, markPositionCache);
|
||||
double probability = getDistanceBasedProbability(w, t, d, markPositionCache) * sidePenalty;
|
||||
final Double passesInTheRightDirectionProbability = passesInTheRightDirection(w, xte1, xte2, portMark);
|
||||
// null would mean "unknown"; no penalty for those cases
|
||||
probability = passesInTheRightDirectionProbability == null ? probability : probability * passesInTheRightDirectionProbability;
|
||||
@@ -869,7 +868,7 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
// at time point t the other competitors are largely not even close to the start waypoint;
|
||||
// this will make start candidates much more likely if many other competitors are also very close to the
|
||||
// start, and it will help ruling out those candidates where someone is practicing a start just for themselves
|
||||
startProbabilityBasedOnOtherCompetitors = getProbabilityForStartCandidateBasedOnOtherCompetitorsBehavior(c, t);
|
||||
startProbabilityBasedOnOtherCompetitors = getProbabilityForStartCandidateBasedOnOtherCompetitorsBehavior(c, t, markPositionCache);
|
||||
if (startProbabilityBasedOnOtherCompetitors != null) {
|
||||
probability *= startProbabilityBasedOnOtherCompetitors;
|
||||
}
|
||||
@@ -932,9 +931,9 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
* A low variance with a positive average (meaning on course side) indicates that everyone else may have started around the
|
||||
* same time, making this a probable late starter's candidate. Therefore, low variance with positive average shall increase
|
||||
* a probability that was low because of a large weighted average distance.
|
||||
*
|
||||
* @param t
|
||||
* the time point at which to consider the other competitors behavior relative to the start waypoint
|
||||
*
|
||||
* @return {@code null} if the {@link #race} has a gate start or the start time is known; a probability between 0..1
|
||||
* (inclusive) where 0 means that based on all but {@code c}'s relation to the start line it seems
|
||||
* completely unlikely that a candidate for {@code c} at time {@code t} could have been a start candidate; 1
|
||||
@@ -942,11 +941,13 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
* a fact that this must have been the start.
|
||||
*
|
||||
*/
|
||||
private Double getProbabilityForStartCandidateBasedOnOtherCompetitorsBehavior(Competitor c, TimePoint t) {
|
||||
private Double getProbabilityForStartCandidateBasedOnOtherCompetitorsBehavior(Competitor c, TimePoint t, MarkPositionAtTimePointCache markPositionCache) {
|
||||
assert t.equals(markPositionCache.getTimePoint());
|
||||
assert race == markPositionCache.getTrackedRace();
|
||||
final Double result;
|
||||
if (race.getStartOfRace(/* inferred */ false) == null && race.isGateStart() != Boolean.TRUE) {
|
||||
final Waypoint start = race.getRace().getCourse().getFirstWaypoint();
|
||||
final Iterable<Pair<Position, Bearing>> crossingInformationForStart = getCrossingInformation(start, t);
|
||||
final Iterable<Pair<Position, Bearing>> crossingInformationForStart = getCrossingInformation(start, t, markPositionCache);
|
||||
if (start == null) {
|
||||
result = 1.0;
|
||||
} else {
|
||||
@@ -960,7 +961,7 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
final Position estimatedPositionAtT = track.getEstimatedPosition(t, /* extrapolate */ true);
|
||||
// consider that a position may not be available for that other competitor, although a track exists
|
||||
if (estimatedPositionAtT != null) {
|
||||
final Distance otherCompetitorsDistanceToStartAtT = getMinDistanceOrNull(calculateDistance(estimatedPositionAtT, start, t));
|
||||
final Distance otherCompetitorsDistanceToStartAtT = getMinDistanceOrNull(calculateDistance(estimatedPositionAtT, start, t, markPositionCache));
|
||||
if (otherCompetitorsDistanceToStartAtT != null) {
|
||||
final Distance crossTrackError;
|
||||
if (startIsLine) {
|
||||
@@ -1095,14 +1096,16 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
* to be negative. If the passing instructions are {@link PassingInstruction#Line}, it checks whether the boat
|
||||
* passed between the two marks.
|
||||
*/
|
||||
private double getSidePenalty(Waypoint w, Position p, TimePoint t, boolean portMark) {
|
||||
private double getSidePenalty(Waypoint w, Position p, TimePoint t, boolean portMark, MarkPositionAtTimePointCache markPositionCache) {
|
||||
assert t.equals(markPositionCache.getTimePoint());
|
||||
assert race == markPositionCache.getTrackedRace();
|
||||
boolean isOnRightSide = true;
|
||||
Distance onWrongSide = new MeterDistance(0);
|
||||
PassingInstruction instruction = getPassingInstructions(w);
|
||||
if (instruction == PassingInstruction.Line) {
|
||||
List<Position> pos = new ArrayList<>();
|
||||
for (Mark m : w.getMarks()) {
|
||||
Position po = race.getOrCreateTrack(m).getEstimatedPosition(t, false);
|
||||
Position po = markPositionCache.getEstimatedPosition(m);
|
||||
if (po == null) {
|
||||
isOnRightSide = true;
|
||||
break;
|
||||
@@ -1130,11 +1133,11 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
|| instruction == PassingInstruction.FixedBearing || instruction == PassingInstruction.Offset) {
|
||||
m = w.getMarks().iterator().next();
|
||||
} else if (instruction == PassingInstruction.Gate) {
|
||||
Util.Pair<Mark, Mark> pair = getPortAndStarboardMarks(t, w);
|
||||
Util.Pair<Mark, Mark> pair = getPortAndStarboardMarks(t, w, markPositionCache);
|
||||
m = portMark ? pair.getA() : pair.getB();
|
||||
}
|
||||
if (m != null) {
|
||||
Util.Pair<Position, Bearing> crossingInfo = Util.get(getCrossingInformation(w, t), portMark ? 0 : 1);
|
||||
Util.Pair<Position, Bearing> crossingInfo = Util.get(getCrossingInformation(w, t, markPositionCache), portMark ? 0 : 1);
|
||||
isOnRightSide = p.crossTrackError(crossingInfo.getA(), crossingInfo.getB().add(new DegreeBearingImpl(90))).getMeters() < 0;
|
||||
if (isOnRightSide == false) {
|
||||
onWrongSide = p.getDistance(crossingInfo.getA());
|
||||
@@ -1188,9 +1191,11 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
/**
|
||||
* @return a probability based on the distance to <code>w</code> and the average leg lengths before and after.
|
||||
*/
|
||||
private Double getDistanceBasedProbability(Waypoint w, TimePoint t, Distance distance) {
|
||||
private Double getDistanceBasedProbability(Waypoint w, TimePoint t, Distance distance, MarkPositionAtTimePointCache markPositionCache) {
|
||||
assert t.equals(markPositionCache.getTimePoint());
|
||||
assert race == markPositionCache.getTrackedRace();
|
||||
final Double result;
|
||||
Distance legLength = getAverageLengthOfAdjacentLegs(t, w);
|
||||
Distance legLength = getAverageLengthOfAdjacentLegs(t, w, markPositionCache);
|
||||
if (legLength != null) {
|
||||
result = 1 / (STRICTNESS_OF_DISTANCE_BASED_PROBABILITY/* Raising this will make it stricter */
|
||||
// reduce distance by 2x the typical HDOP, accounting for the possibility that some distance from the mark
|
||||
@@ -1205,26 +1210,38 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
/**
|
||||
* @return an average of the estimated legs before and after <code>w</code>.
|
||||
*/
|
||||
private Distance getAverageLengthOfAdjacentLegs(TimePoint t, Waypoint w) {
|
||||
Course course = race.getRace().getCourse();
|
||||
if (w == course.getFirstWaypoint()) {
|
||||
return race.getTrackedLegStartingAt(w).getGreatCircleDistance(t);
|
||||
private Distance getAverageLengthOfAdjacentLegs(TimePoint t, Waypoint w, MarkPositionAtTimePointCache markPositionCache) {
|
||||
assert t.equals(markPositionCache.getTimePoint());
|
||||
assert race == markPositionCache.getTrackedRace();
|
||||
final Distance result;
|
||||
final Course course = race.getRace().getCourse();
|
||||
if (course.getNumberOfWaypoints() < 2) {
|
||||
result = null;
|
||||
} else if (w == course.getFirstWaypoint()) {
|
||||
result = race.getTrackedLegStartingAt(w).getGreatCircleDistance(t, markPositionCache);
|
||||
} else if (w == course.getLastWaypoint()) {
|
||||
return race.getTrackedLegFinishingAt(w).getGreatCircleDistance(t);
|
||||
result = race.getTrackedLegFinishingAt(w).getGreatCircleDistance(t, markPositionCache);
|
||||
} else {
|
||||
Distance before = race.getTrackedLegStartingAt(w).getGreatCircleDistance(t);
|
||||
Distance after = race.getTrackedLegFinishingAt(w).getGreatCircleDistance(t);
|
||||
Distance before = race.getTrackedLegStartingAt(w).getGreatCircleDistance(t, markPositionCache);
|
||||
Distance after = race.getTrackedLegFinishingAt(w).getGreatCircleDistance(t, markPositionCache);
|
||||
if (after != null && before != null) {
|
||||
return new MeterDistance(before.add(after).getMeters() / 2);
|
||||
result = new MeterDistance(before.add(after).getMeters() / 2);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the distance from p to each mark of w at the timepoint t.
|
||||
*
|
||||
* @param markPositionCache
|
||||
* a mark position cache for time point {@code t} for this finder's {@link #race}
|
||||
*/
|
||||
private List<Distance> calculateDistance(Position p, Waypoint w, TimePoint t) {
|
||||
private List<Distance> calculateDistance(Position p, Waypoint w, TimePoint t, MarkPositionAtTimePointCache markPositionCache) {
|
||||
assert t.equals(markPositionCache.getTimePoint());
|
||||
assert race == markPositionCache.getTrackedRace();
|
||||
final List<Distance> distances = new ArrayList<>();
|
||||
PassingInstruction instruction = getPassingInstructions(w);
|
||||
boolean singleMark = false;
|
||||
@@ -1236,25 +1253,25 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
singleMark = true;
|
||||
break;
|
||||
case Gate:
|
||||
Util.Pair<Mark, Mark> posGate = getPortAndStarboardMarks(t, w);
|
||||
Util.Pair<Mark, Mark> posGate = getPortAndStarboardMarks(t, w, markPositionCache);
|
||||
if (posGate.getA() != null) {
|
||||
Position portGatePosition = race.getOrCreateTrack(posGate.getA()).getEstimatedPosition(t, false);
|
||||
Position portGatePosition = markPositionCache.getEstimatedPosition(posGate.getA());
|
||||
distances.add(portGatePosition != null ? p.getDistance(portGatePosition) : null);
|
||||
} else {
|
||||
distances.add(null);
|
||||
}
|
||||
if (posGate.getB() != null) {
|
||||
Position starboardGatePosition = race.getOrCreateTrack(posGate.getB()).getEstimatedPosition(t, false);
|
||||
Position starboardGatePosition = markPositionCache.getEstimatedPosition(posGate.getB());
|
||||
distances.add(starboardGatePosition != null ? p.getDistance(starboardGatePosition) : null);
|
||||
} else {
|
||||
distances.add(null);
|
||||
}
|
||||
break;
|
||||
case Line:
|
||||
Util.Pair<Mark, Mark> posLine = getPortAndStarboardMarks(t, w);
|
||||
Util.Pair<Mark, Mark> posLine = getPortAndStarboardMarks(t, w, markPositionCache);
|
||||
if (posLine.getA() != null && posLine.getB() != null) {
|
||||
Position portLinePosition = race.getOrCreateTrack(posLine.getA()).getEstimatedPosition(t, false);
|
||||
Position starboardLinePosition = race.getOrCreateTrack(posLine.getB()).getEstimatedPosition(t, false);
|
||||
Position portLinePosition = markPositionCache.getEstimatedPosition(posLine.getA());
|
||||
Position starboardLinePosition = markPositionCache.getEstimatedPosition(posLine.getB());
|
||||
distances.add((portLinePosition != null && starboardLinePosition != null) ? p.getDistanceToLine(
|
||||
portLinePosition, starboardLinePosition).abs() : null);
|
||||
}
|
||||
@@ -1270,8 +1287,7 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
break;
|
||||
}
|
||||
if (singleMark) {
|
||||
Position markPosition = race.getOrCreateTrack(w.getMarks().iterator().next())
|
||||
.getEstimatedPosition(t, false);
|
||||
Position markPosition = markPositionCache.getEstimatedPosition(w.getMarks().iterator().next());
|
||||
distances.add(markPosition != null ? p.getDistance(markPosition) : null);
|
||||
}
|
||||
return distances;
|
||||
@@ -1292,44 +1308,46 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
* @return all possible ways to pass a waypoint, described as a position and a bearing. The line out of those two
|
||||
* must be crossed.
|
||||
*/
|
||||
private Iterable<Util.Pair<Position, Bearing>> getCrossingInformation(Waypoint w, TimePoint t) {
|
||||
private Iterable<Util.Pair<Position, Bearing>> getCrossingInformation(Waypoint w, TimePoint t, MarkPositionAtTimePointCache markPositionCache) {
|
||||
assert t.equals(markPositionCache.getTimePoint());
|
||||
assert race == markPositionCache.getTrackedRace();
|
||||
List<Util.Pair<Position, Bearing>> result = new ArrayList<>();
|
||||
PassingInstruction instruction = getPassingInstructions(w);
|
||||
if (instruction == PassingInstruction.Line) {
|
||||
Util.Pair<Mark, Mark> marks = getPortAndStarboardMarks(t, w);
|
||||
Util.Pair<Mark, Mark> marks = getPortAndStarboardMarks(t, w, markPositionCache);
|
||||
Position portPosition = null;
|
||||
Bearing b = null;
|
||||
Mark portMark = marks.getA();
|
||||
Mark starBoardMark = marks.getB();
|
||||
if (portMark != null && starBoardMark != null) {
|
||||
portPosition = race.getOrCreateTrack(portMark).getEstimatedPosition(t, false);
|
||||
Position starboardPosition = race.getOrCreateTrack(starBoardMark).getEstimatedPosition(t, false);
|
||||
portPosition = markPositionCache.getEstimatedPosition(portMark);
|
||||
Position starboardPosition = markPositionCache.getEstimatedPosition(starBoardMark);
|
||||
if (portPosition != null && starboardPosition != null) {
|
||||
b = portPosition.getBearingGreatCircle(starboardPosition);
|
||||
result.add(new Util.Pair<Position, Bearing>(portPosition, b));
|
||||
}
|
||||
}
|
||||
} else if (instruction == PassingInstruction.Gate) {
|
||||
Position before = race.getApproximatePosition(race.getTrackedLegFinishingAt(w).getLeg().getFrom(), t);
|
||||
Position after = race.getApproximatePosition(race.getTrackedLegStartingAt(w).getLeg().getTo(), t);
|
||||
Util.Pair<Mark, Mark> pos = getPortAndStarboardMarks(t, w);
|
||||
Position before = markPositionCache.getApproximatePosition(race.getTrackedLegFinishingAt(w).getLeg().getFrom());
|
||||
Position after = markPositionCache.getApproximatePosition(race.getTrackedLegStartingAt(w).getLeg().getTo());
|
||||
Util.Pair<Mark, Mark> pos = getPortAndStarboardMarks(t, w, markPositionCache);
|
||||
Mark portMark = pos.getA();
|
||||
if (portMark != null) {
|
||||
Position portPosition = race.getOrCreateTrack(portMark).getEstimatedPosition(t, false);
|
||||
Position portPosition = markPositionCache.getEstimatedPosition(portMark);
|
||||
Bearing crossingPort = before.getBearingGreatCircle(portPosition).middle(
|
||||
after.getBearingGreatCircle(portPosition));
|
||||
result.add(new Util.Pair<Position, Bearing>(portPosition, crossingPort));
|
||||
}
|
||||
Mark starboardMark = pos.getB();
|
||||
if (starboardMark != null) {
|
||||
Position starboardPosition = race.getOrCreateTrack(starboardMark).getEstimatedPosition(t, false);
|
||||
Position starboardPosition = markPositionCache.getEstimatedPosition(starboardMark);
|
||||
Bearing crossingStarboard = before.getBearingGreatCircle(starboardPosition).middle(
|
||||
after.getBearingGreatCircle(starboardPosition));
|
||||
result.add(new Util.Pair<Position, Bearing>(starboardPosition, crossingStarboard));
|
||||
}
|
||||
} else { // single mark
|
||||
Bearing b = null;
|
||||
Position p = race.getOrCreateTrack(w.getMarks().iterator().next()).getEstimatedPosition(t, false);
|
||||
Position p = markPositionCache.getEstimatedPosition(w.getMarks().iterator().next());
|
||||
if (instruction == PassingInstruction.FixedBearing) {
|
||||
b = w.getFixedBearing();
|
||||
} else {
|
||||
@@ -1339,23 +1357,23 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
// orthogonally to the adjacent leg:
|
||||
if (w == race.getRace().getCourse().getFirstWaypoint()) {
|
||||
if (instruction == PassingInstruction.None || instruction == PassingInstruction.Single_Unknown) {
|
||||
b = race.getTrackedLegStartingAt(w).getLegBearing(t).add(new DegreeBearingImpl(90));
|
||||
b = markPositionCache.getLegBearing(race.getTrackedLegStartingAt(w)).add(new DegreeBearingImpl(90));
|
||||
result.add(new Pair<>(p, b));
|
||||
b = race.getTrackedLegStartingAt(w).getLegBearing(t).add(new DegreeBearingImpl(270));
|
||||
b = markPositionCache.getLegBearing(race.getTrackedLegStartingAt(w)).add(new DegreeBearingImpl(270));
|
||||
} else {
|
||||
b = race.getTrackedLegStartingAt(w).getLegBearing(t).add(new DegreeBearingImpl(instruction == PassingInstruction.Port ? 90 : 270));
|
||||
b = markPositionCache.getLegBearing(race.getTrackedLegStartingAt(w)).add(new DegreeBearingImpl(instruction == PassingInstruction.Port ? 90 : 270));
|
||||
}
|
||||
} else if (w == race.getRace().getCourse().getLastWaypoint()) {
|
||||
if (instruction == PassingInstruction.None || instruction == PassingInstruction.Single_Unknown) {
|
||||
b = race.getTrackedLegFinishingAt(w).getLegBearing(t).add(new DegreeBearingImpl(90));
|
||||
b = markPositionCache.getLegBearing(race.getTrackedLegFinishingAt(w)).add(new DegreeBearingImpl(90));
|
||||
result.add(new Pair<>(p, b));
|
||||
b = race.getTrackedLegFinishingAt(w).getLegBearing(t).add(new DegreeBearingImpl(270));
|
||||
b = markPositionCache.getLegBearing(race.getTrackedLegFinishingAt(w)).add(new DegreeBearingImpl(270));
|
||||
} else {
|
||||
b = race.getTrackedLegFinishingAt(w).getLegBearing(t).add(new DegreeBearingImpl(instruction == PassingInstruction.Port ? 90 : 270));
|
||||
b = markPositionCache.getLegBearing(race.getTrackedLegFinishingAt(w)).add(new DegreeBearingImpl(instruction == PassingInstruction.Port ? 90 : 270));
|
||||
}
|
||||
} else {
|
||||
Bearing before = race.getTrackedLegFinishingAt(w).getLegBearing(t);
|
||||
Bearing after = race.getTrackedLegStartingAt(w).getLegBearing(t);
|
||||
Bearing before = markPositionCache.getLegBearing(race.getTrackedLegFinishingAt(w));
|
||||
Bearing after = markPositionCache.getLegBearing(race.getTrackedLegStartingAt(w));
|
||||
if (before != null && after != null) {
|
||||
b = before.middle(after.reverse());
|
||||
}
|
||||
@@ -1367,14 +1385,17 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param markPositionCache
|
||||
* a mark position cache for this finder's {@link #race} for time point {@code t}
|
||||
* @return the marks of a waypoint with two marks in the order port, starboard (when approaching the waypoint from
|
||||
* the direction of the waypoint beforehand.
|
||||
*/
|
||||
private Util.Pair<Mark, Mark> getPortAndStarboardMarks(TimePoint t, Waypoint w) {
|
||||
private Util.Pair<Mark, Mark> getPortAndStarboardMarks(TimePoint t, Waypoint w, MarkPositionAtTimePointCache markPositionCache) {
|
||||
assert t.equals(markPositionCache.getTimePoint());
|
||||
assert race == markPositionCache.getTrackedRace();
|
||||
List<Position> markPositions = new ArrayList<Position>();
|
||||
for (Mark mark : w.getMarks()) {
|
||||
final Position estimatedMarkPosition = race.getOrCreateTrack(mark).getEstimatedPosition(t, /* extrapolate */
|
||||
false);
|
||||
final Position estimatedMarkPosition = markPositionCache.getEstimatedPosition(mark);
|
||||
if (estimatedMarkPosition == null) {
|
||||
return new Util.Pair<Mark, Mark>(null, null);
|
||||
}
|
||||
@@ -1389,8 +1410,8 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
return new Util.Pair<Mark, Mark>(null, null);
|
||||
}
|
||||
final boolean isStartLine = indexOfWaypoint == 0;
|
||||
final Bearing legDeterminingDirectionBearing = race.getTrackedLeg(
|
||||
legs.get(isStartLine ? 0 : indexOfWaypoint - 1)).getLegBearing(t);
|
||||
final Bearing legDeterminingDirectionBearing = markPositionCache.getLegBearing(race.getTrackedLeg(
|
||||
legs.get(isStartLine ? 0 : indexOfWaypoint - 1)));
|
||||
if (legDeterminingDirectionBearing == null) {
|
||||
return new Util.Pair<Mark, Mark>(null, null);
|
||||
}
|
||||
@@ -1414,8 +1435,9 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
final TimePoint newNonInferredStartTime = race.getStartOfRace(/* inferred */ false);
|
||||
final TimePoint newTimePointWhenToStartConsideringCandidates = getTimePointWhenToStartConsideringCandidates(newNonInferredStartTime);
|
||||
if (!Util.equalsWithNull(newTimePointWhenToStartConsideringCandidates, timeRangeForValidCandidates.from())) {
|
||||
final TimePoint oldTimePointWhenToStartConsideringCandidates = timeRangeForValidCandidates.from();
|
||||
timeRangeForValidCandidates = new TimeRangeImpl(newTimePointWhenToStartConsideringCandidates, timeRangeForValidCandidates.to());
|
||||
result = updateCandiatesAfterRaceTimeRangeChanged(newTimePointWhenToStartConsideringCandidates, timeRangeForValidCandidates.from());
|
||||
result = updateCandiatesAfterRaceTimeRangeChanged(newTimePointWhenToStartConsideringCandidates, oldTimePointWhenToStartConsideringCandidates);
|
||||
} else {
|
||||
result = Collections.emptyMap();
|
||||
}
|
||||
@@ -1427,12 +1449,10 @@ public class CandidateFinderImpl implements CandidateFinder {
|
||||
TimePoint oldFinishedTime, TimePoint newFinishedTime) {
|
||||
final Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> result;
|
||||
final TimePoint newTimePointWhenToFinishConsideringCandidates = getTimePointWhenToFinishConsideringCandidates(newFinishedTime);
|
||||
final TimePoint oldTimePointWhenToFinishConsideringCandidates = timeRangeForValidCandidates.to();
|
||||
if (!Util.equalsWithNull(timeRangeForValidCandidates.to(), newTimePointWhenToFinishConsideringCandidates)) {
|
||||
final TimePoint oldTimePointWhenToFinishConsideringCandidates = timeRangeForValidCandidates.to();
|
||||
timeRangeForValidCandidates = new TimeRangeImpl(timeRangeForValidCandidates.from(), newTimePointWhenToFinishConsideringCandidates);
|
||||
result = updateCandiatesAfterRaceTimeRangeChanged(
|
||||
oldTimePointWhenToFinishConsideringCandidates,
|
||||
newTimePointWhenToFinishConsideringCandidates);
|
||||
result = updateCandiatesAfterRaceTimeRangeChanged(oldTimePointWhenToFinishConsideringCandidates, newTimePointWhenToFinishConsideringCandidates);
|
||||
} else {
|
||||
result = Collections.emptyMap();
|
||||
}
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ public interface DoubleVectorFixImporter {
|
||||
* @throws IOException
|
||||
* if there is a problem while reading the file
|
||||
*/
|
||||
void importFixes(InputStream inputStream, Callback callback, String sourceName)
|
||||
void importFixes(InputStream inputStream, Callback callback, String filename, String sourceName)
|
||||
throws FormatNotSupportedException, IOException;
|
||||
|
||||
/**
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package com.sap.sailing.domain.tracking;
|
||||
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
/**
|
||||
* Some calculations that span several method calls require access to the same {@link Mark} positions for the same
|
||||
* {@link TimePoint} within the scope of the same {@link TrackedRace} repeatedly. Usually, for such a compound
|
||||
* calculation it doesn't matter whether a new fix has arrived in between, making it valid to cache the mark
|
||||
* positions---once calculated---for the remainder of the compound operation. Based on these positions, approximate
|
||||
* waypoint positions and leg bearings can also be calculated and cached.
|
||||
* <p>
|
||||
*
|
||||
* Implementations of this interface may cache the results of computing a mark's position for the duration of this
|
||||
* object.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public interface MarkPositionAtTimePointCache {
|
||||
/**
|
||||
* Gets the non-extrapolated mark position in this cache's tracked race at the time point
|
||||
* specified.
|
||||
*
|
||||
* @see TrackedRace#getOrCreateTrack(Mark)
|
||||
* @see GPSFixTrack#getEstimatedPosition(TimePoint, boolean)
|
||||
*/
|
||||
Position getEstimatedPosition(Mark mark);
|
||||
|
||||
/**
|
||||
* Gets the approximate position of a waypoint in the scope of this cache's tracked race at
|
||||
* the time point specified.
|
||||
*
|
||||
* @see TrackedRace#getApproximatePosition(Waypoint, TimePoint)
|
||||
*/
|
||||
Position getApproximatePosition(Waypoint waypoint);
|
||||
|
||||
/**
|
||||
* Gets the bearing of the tracked leg at the time point specified, optionally based on mark position
|
||||
* information already stored in this cache.
|
||||
*
|
||||
* @see TrackedLeg#getLegBearing(TimePoint)
|
||||
*/
|
||||
Bearing getLegBearing(TrackedLeg trackedLeg);
|
||||
|
||||
/**
|
||||
* @return the time point for which this cache holds values
|
||||
*/
|
||||
TimePoint getTimePoint();
|
||||
|
||||
/**
|
||||
* @return the tracked race for which this cache holds values
|
||||
*/
|
||||
TrackedRace getTrackedRace();
|
||||
}
|
||||
@@ -56,6 +56,16 @@ public interface TrackedLeg extends Serializable {
|
||||
|
||||
Bearing getLegBearing(TimePoint at);
|
||||
|
||||
/**
|
||||
* Same as {@link #getLegBearing(TimePoint)}, but giving the caller the possibility to provide a cache for
|
||||
* mark positions and related position and bearing data
|
||||
*
|
||||
* @param markPositionCache
|
||||
* a cache for this tracked leg's {@link MarkPositionAtTimePointCache#getTrackedRace() race} and the
|
||||
* {@link MarkPositionAtTimePointCache#getTimePoint() timePoint} passed
|
||||
*/
|
||||
Bearing getLegBearing(TimePoint at, MarkPositionAtTimePointCache markPositionCache);
|
||||
|
||||
/**
|
||||
* Returns the positive (absolute) distance of <code>p</code> to this leg's course middle line at <code>timePoint</code>,
|
||||
* based on the position of the waypoints delimiting this leg at that time.
|
||||
@@ -80,6 +90,16 @@ public interface TrackedLeg extends Serializable {
|
||||
*/
|
||||
Distance getGreatCircleDistance(TimePoint timePoint);
|
||||
|
||||
/**
|
||||
* Same as {@link #getGreatCircleDistance(TimePoint)}, but giving the caller the possibility to provide a cache for
|
||||
* mark positions and related position and bearing data
|
||||
*
|
||||
* @param markPositionCache
|
||||
* a cache for this tracked leg's {@link MarkPositionAtTimePointCache#getTrackedRace() race} and the
|
||||
* {@link MarkPositionAtTimePointCache#getTimePoint() timePoint} passed
|
||||
*/
|
||||
Distance getGreatCircleDistance(TimePoint timePoint, MarkPositionAtTimePointCache markPositionCache);
|
||||
|
||||
/**
|
||||
* If the current {@link #getLeg() leg} is +/- {@link TrackedLegImpl#UPWIND_DOWNWIND_TOLERANCE_IN_DEG} degrees
|
||||
* collinear with the wind's bearing, <code>pos1</code> is projected onto the line crossing <code>pos2</code> in the
|
||||
@@ -144,7 +164,8 @@ public interface TrackedLeg extends Serializable {
|
||||
* is not available
|
||||
* @throws NoWindException no wind available. unable to determine legtypes for given timepoint
|
||||
*/
|
||||
Duration getEstimatedTimeToComplete(PolarDataService polarDataService, TimePoint timepoint) throws NotEnoughDataHasBeenAddedException, NoWindException;
|
||||
Duration getEstimatedTimeToComplete(PolarDataService polarDataService, TimePoint timepoint, MarkPositionAtTimePointCache markPositionCache)
|
||||
throws NotEnoughDataHasBeenAddedException, NoWindException;
|
||||
|
||||
/**
|
||||
* Computes the windward distance (for upwind/downwind legs) or the along-course distance (for reaching legs) at a reference time point
|
||||
|
||||
@@ -49,6 +49,7 @@ import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||
import com.sap.sailing.domain.polars.PolarDataService;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
||||
import com.sap.sailing.domain.tracking.impl.NonCachingMarkPositionAtTimePointCache;
|
||||
import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.IsManagedByCache;
|
||||
@@ -316,8 +317,22 @@ public interface TrackedRace extends Serializable, IsManagedByCache<SharedDomain
|
||||
* If the <code>waypoint</code> only has one {@link #getMarks() mark}, its position at time <code>timePoint</code>
|
||||
* is returned. Otherwise, the center of gravity between the mark positions is computed and returned.
|
||||
*/
|
||||
Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint);
|
||||
default Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint) {
|
||||
return getApproximatePosition(waypoint, timePoint, new NonCachingMarkPositionAtTimePointCache(this, timePoint));
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #getApproximatePosition(Waypoint, TimePoint)}, but giving the caller the possibility to pass a
|
||||
* cache of mark positions and related information that can help speed up compound operations requiring frequent
|
||||
* access to the same marks in the same race for the same time point.
|
||||
*
|
||||
* @param markPositionCache
|
||||
* a cache for this {@link MarkPositionAtTimePointCache#getTrackedRace() race} and the
|
||||
* {@link MarkPositionAtTimePointCache#getTimePoint() timePoint} passed
|
||||
*/
|
||||
Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint,
|
||||
MarkPositionAtTimePointCache markPositionCache);
|
||||
|
||||
/**
|
||||
* Checks whether the {@link Wind#getTimePoint()} is in range of start and end {@link TimePoint}s plus extra time
|
||||
* for wind recording. If, based on a {@link RaceExecutionOrderProvider}, there is no previous race that takes the
|
||||
@@ -946,4 +961,5 @@ public interface TrackedRace extends Serializable, IsManagedByCache<SharedDomain
|
||||
* @return all currently attached {@link RaceLog}s or an empty Iterable if there aren't any
|
||||
*/
|
||||
Iterable<RaceLog> getAttachedRaceLogs();
|
||||
|
||||
}
|
||||
+6
-4
@@ -723,7 +723,7 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends MappedTra
|
||||
* then the next fix is added to the result interval. This is because for that next fix, <code>fix</code> in that case will be relevant
|
||||
* for speed estimation because it's the closest fix.
|
||||
*/
|
||||
protected Util.Pair<TimePoint, TimePoint> getTimeIntervalWhoseEstimatedSpeedMayHaveChangedAfterAddingFix(FixType fix) {
|
||||
protected TimeRange getTimeIntervalWhoseEstimatedSpeedMayHaveChangedAfterAddingFix(FixType fix) {
|
||||
TimePoint intervalStart = null;
|
||||
TimePoint intervalEnd = null;
|
||||
lockForRead();
|
||||
@@ -783,7 +783,7 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends MappedTra
|
||||
} finally {
|
||||
unlockAfterRead();
|
||||
}
|
||||
return new Util.Pair<TimePoint, TimePoint>(intervalStart, intervalEnd);
|
||||
return new TimeRangeImpl(intervalStart, intervalEnd);
|
||||
}
|
||||
|
||||
protected FixType createDummyGPSFix(TimePoint at) {
|
||||
@@ -1075,8 +1075,10 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends MappedTra
|
||||
unlockAfterRead();
|
||||
}
|
||||
}
|
||||
for (GPSTrackListener<ItemType, FixType> listener : getListeners()) {
|
||||
listener.gpsFixReceived(fix, getTrackedItem(), firstFixInTrack);
|
||||
if (result) {
|
||||
for (GPSTrackListener<ItemType, FixType> listener : getListeners()) {
|
||||
listener.gpsFixReceived(fix, getTrackedItem(), firstFixInTrack);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package com.sap.sailing.domain.tracking.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class MarkPositionAtTimePointCacheImpl extends NonCachingMarkPositionAtTimePointCache {
|
||||
private final Map<Mark, Position> estimatedMarkPositions;
|
||||
private final Map<Waypoint, Position> approximateWaypointPositions;
|
||||
private final Map<TrackedLeg, Bearing> legBearings;
|
||||
|
||||
public MarkPositionAtTimePointCacheImpl(TrackedRace trackedRace, TimePoint timePoint) {
|
||||
super(trackedRace, timePoint);
|
||||
estimatedMarkPositions = new HashMap<>();
|
||||
approximateWaypointPositions = new HashMap<>();
|
||||
legBearings = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getEstimatedPosition(Mark mark) {
|
||||
final Position result;
|
||||
if (estimatedMarkPositions.containsKey(mark)) {
|
||||
result = estimatedMarkPositions.get(mark);
|
||||
} else {
|
||||
result = super.getEstimatedPosition(mark);
|
||||
estimatedMarkPositions.put(mark, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getApproximatePosition(Waypoint waypoint) {
|
||||
final Position result;
|
||||
if (approximateWaypointPositions.containsKey(waypoint)) {
|
||||
result = approximateWaypointPositions.get(waypoint);
|
||||
} else {
|
||||
result = super.getApproximatePosition(waypoint);
|
||||
approximateWaypointPositions.put(waypoint, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getLegBearing(TrackedLeg trackedLeg) {
|
||||
final Bearing result;
|
||||
if (legBearings.containsKey(trackedLeg)) {
|
||||
result = legBearings.get(trackedLeg);
|
||||
} else {
|
||||
result = super.getLegBearing(trackedLeg);
|
||||
legBearings.put(trackedLeg, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
+22
-18
@@ -13,8 +13,10 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.GPSTrackListener;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.TimeRange;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.impl.TimeRangeImpl;
|
||||
import com.sap.sse.concurrent.LockUtil;
|
||||
import com.sap.sse.concurrent.NamedReentrantReadWriteLock;
|
||||
import com.sap.sse.util.impl.ArrayListNavigableSet;
|
||||
@@ -58,9 +60,9 @@ public class MaxSpeedCache<ItemType, FixType extends GPSFix> implements GPSTrack
|
||||
* Keys are the "from" time points as passed to {@link #getMaxSpeed(TimePoint, TimePoint)}. Values are navigable
|
||||
* sets of pairs whose {@link Pair#getA() a} component is the "to" parameter as passed to
|
||||
* {@link #getMaxSpeed(TimePoint, TimePoint)}, and whose {@link Pair#getB() b} component is the track's fix where
|
||||
* the averaged maximum speed for that interval was achieved together with the averaged speed at that point. The
|
||||
* navigable set is ordered according to ascending <code>to</code> time points, yielding shorter cache intervals
|
||||
* before longer intervals.
|
||||
* the maximum speed for that interval was achieved together with the speed at that point. The navigable set is
|
||||
* ordered according to ascending <code>to</code> time points, yielding shorter cache intervals before longer
|
||||
* intervals.
|
||||
*/
|
||||
private final Map<TimePoint, NavigableSet<Util.Pair<TimePoint, Util.Pair<FixType, Speed>>>> cache;
|
||||
|
||||
@@ -88,7 +90,7 @@ public class MaxSpeedCache<ItemType, FixType extends GPSFix> implements GPSTrack
|
||||
@Override
|
||||
public void gpsFixReceived(FixType fix, ItemType item, boolean firstFixInTrack) {
|
||||
// find the invalidation interval such that getFixesRelevantForSpeedEstimation, when passed any time point from that interval, produces "fix"
|
||||
Util.Pair<TimePoint, TimePoint> invalidationInterval = track.getTimeIntervalWhoseEstimatedSpeedMayHaveChangedAfterAddingFix(fix);
|
||||
TimeRange invalidationInterval = track.getTimeIntervalWhoseEstimatedSpeedMayHaveChangedAfterAddingFix(fix);
|
||||
LockUtil.lockForWrite(lock);
|
||||
HashMap<TimePoint, NavigableSet<Util.Pair<TimePoint, Util.Pair<FixType, Speed>>>> additionalCacheEntries =
|
||||
new HashMap<TimePoint, NavigableSet<Util.Pair<TimePoint, Util.Pair<FixType, Speed>>>>();
|
||||
@@ -131,33 +133,35 @@ public class MaxSpeedCache<ItemType, FixType extends GPSFix> implements GPSTrack
|
||||
|
||||
private Map<TimePoint, NavigableSet<Util.Pair<TimePoint, Util.Pair<FixType, Speed>>>> invalidateEntriesAndReturnAdditionalCacheEntries(
|
||||
Entry<TimePoint, NavigableSet<Util.Pair<TimePoint, Util.Pair<FixType, Speed>>>> cacheEntry,
|
||||
Util.Pair<TimePoint, TimePoint> invalidationInterval) {
|
||||
TimeRange invalidationInterval) {
|
||||
assert lock.writeLock().isHeldByCurrentThread();
|
||||
// cannot modify cache here because caller is in an iteration over cache's entry set; request additions by returning them
|
||||
Map<TimePoint, NavigableSet<Util.Pair<TimePoint, Util.Pair<FixType, Speed>>>> result = new HashMap<>();
|
||||
if (!cacheEntry.getKey().after(invalidationInterval.getB())) {
|
||||
final TimePoint cacheEntryFrom = cacheEntry.getKey();
|
||||
if (!cacheEntryFrom.after(invalidationInterval.to())) {
|
||||
// invalidation can only become necessary if the cache entry doesn't start after the end of the invalidation interval
|
||||
TimePoint croppedFrom; // start of the remaining valid part of the cache entries
|
||||
if (cacheEntry.getKey().before(invalidationInterval.getA())) {
|
||||
croppedFrom = cacheEntry.getKey();
|
||||
} else {
|
||||
croppedFrom = invalidationInterval.getB(); // cache entry starts in the invalidationInterval; earliest valid point is end of invalidation interval
|
||||
}
|
||||
// now scan all entries whose "to" is at or after the invalidationInterval's start:
|
||||
for (Iterator<Util.Pair<TimePoint, Util.Pair<FixType, Speed>>> toAndResultIter = cacheEntry.getValue().tailSet(
|
||||
new Util.Pair<TimePoint, Util.Pair<FixType, Speed>>(invalidationInterval.getA(), null), /* inclusive */ true).iterator();
|
||||
new Util.Pair<TimePoint, Util.Pair<FixType, Speed>>(invalidationInterval.from(), null), /* inclusive */ true).iterator();
|
||||
toAndResultIter.hasNext(); ) {
|
||||
Util.Pair<TimePoint, Util.Pair<FixType, Speed>> toAndResult = toAndResultIter.next();
|
||||
// cacheEntry's from is before or in the invalidation interval; the current "to" in this loop iteration is in or after the interval
|
||||
// and at or after "from"; in any case the record needs to be deleted:
|
||||
toAndResultIter.remove();
|
||||
// if the current "to" is at or after croppedFrom, check if the old max fix is in the cropped interval; if so, request
|
||||
// creation of a new cache entry:
|
||||
// check if the old max fix is outside the invalidation interval; if so, request creation of a new cropped cache entry
|
||||
if (toAndResult.getB() != null) {
|
||||
final TimePoint maxFixTimePoint = toAndResult.getB().getA().getTimePoint();
|
||||
if (!toAndResult.getA().before(croppedFrom) && !maxFixTimePoint.before(croppedFrom)
|
||||
&& !maxFixTimePoint.after(toAndResult.getA())) {
|
||||
addEntryToMap(croppedFrom, toAndResult.getA(), toAndResult.getB(), result);
|
||||
if (!invalidationInterval.includes(maxFixTimePoint)) {
|
||||
final TimePoint cacheEntryTo = toAndResult.getA();
|
||||
final TimeRange croppedCacheEntryTimeRangeContainingMaxFix;
|
||||
if (invalidationInterval.startsAfter(maxFixTimePoint)) {
|
||||
croppedCacheEntryTimeRangeContainingMaxFix = new TimeRangeImpl(cacheEntryFrom, invalidationInterval.from());
|
||||
} else { // invalidation interval must end before the maxFixTimePoint
|
||||
assert invalidationInterval.endsBefore(maxFixTimePoint);
|
||||
croppedCacheEntryTimeRangeContainingMaxFix = new TimeRangeImpl(invalidationInterval.to(), cacheEntryTo);
|
||||
}
|
||||
addEntryToMap(croppedCacheEntryTimeRangeContainingMaxFix.from(),
|
||||
croppedCacheEntryTimeRangeContainingMaxFix.to(), toAndResult.getB(), result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.sap.sailing.domain.tracking.impl;
|
||||
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class NonCachingMarkPositionAtTimePointCache implements MarkPositionAtTimePointCache {
|
||||
private final TrackedRace trackedRace;
|
||||
private final TimePoint timePoint;
|
||||
|
||||
public NonCachingMarkPositionAtTimePointCache(TrackedRace trackedRace, TimePoint timePoint) {
|
||||
super();
|
||||
this.trackedRace = trackedRace;
|
||||
this.timePoint = timePoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getEstimatedPosition(Mark mark) {
|
||||
return trackedRace.getOrCreateTrack(mark).getEstimatedPosition(timePoint, /* extrapolate */ false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getApproximatePosition(Waypoint waypoint) {
|
||||
return trackedRace.getApproximatePosition(waypoint, timePoint, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getLegBearing(TrackedLeg trackedLeg) {
|
||||
return trackedLeg.getLegBearing(timePoint, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrackedRace getTrackedRace() {
|
||||
return trackedRace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePoint getTimePoint() {
|
||||
return timePoint;
|
||||
}
|
||||
}
|
||||
+12
@@ -28,6 +28,8 @@ import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.WindImpl;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.common.tracking.SensorFix;
|
||||
import com.sap.sailing.domain.tracking.DynamicSensorFixTrack;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRaceStatus;
|
||||
@@ -740,6 +742,16 @@ public class TrackBasedEstimationWindTrackImpl extends VirtualWindTrackImpl {
|
||||
scheduleCacheRefresh(startOfInvalidation, endOfInvalidation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void competitorSensorFixAdded(Competitor competitor, String trackName, SensorFix fix) {
|
||||
// no action required
|
||||
}
|
||||
|
||||
@Override
|
||||
public void competitorSensorTrackAdded(DynamicSensorFixTrack<Competitor, ?> track) {
|
||||
// no action required
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+23
-6
@@ -39,6 +39,7 @@ import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuse
|
||||
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||
import com.sap.sailing.domain.polars.PolarDataService;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
@@ -204,8 +205,15 @@ public class TrackedLegImpl implements TrackedLeg {
|
||||
|
||||
@Override
|
||||
public Bearing getLegBearing(TimePoint at) {
|
||||
Position startMarkPos = getTrackedRace().getApproximatePosition(getLeg().getFrom(), at);
|
||||
Position endMarkPos = getTrackedRace().getApproximatePosition(getLeg().getTo(), at);
|
||||
return getLegBearing(at, new MarkPositionAtTimePointCacheImpl(getTrackedRace(), at));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getLegBearing(TimePoint at, MarkPositionAtTimePointCache markPositionCache) {
|
||||
assert markPositionCache.getTimePoint().equals(at);
|
||||
assert markPositionCache.getTrackedRace() == getTrackedRace();
|
||||
Position startMarkPos = markPositionCache.getApproximatePosition(getLeg().getFrom());
|
||||
Position endMarkPos = markPositionCache.getApproximatePosition(getLeg().getTo());
|
||||
Bearing legBearing = (startMarkPos != null && endMarkPos != null) ? startMarkPos.getBearingGreatCircle(endMarkPos) : null;
|
||||
return legBearing;
|
||||
}
|
||||
@@ -337,10 +345,12 @@ public class TrackedLegImpl implements TrackedLeg {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getGreatCircleDistance(TimePoint timePoint) {
|
||||
public Distance getGreatCircleDistance(TimePoint timePoint, MarkPositionAtTimePointCache markPositionCache) {
|
||||
assert markPositionCache.getTimePoint().equals(timePoint);
|
||||
assert markPositionCache.getTrackedRace() == getTrackedRace();
|
||||
final Distance result;
|
||||
final Position approximatePositionOfFrom = getTrackedRace().getApproximatePosition(getLeg().getFrom(), timePoint);
|
||||
final Position approximatePositionOfTo = getTrackedRace().getApproximatePosition(getLeg().getTo(), timePoint);
|
||||
final Position approximatePositionOfFrom = markPositionCache.getApproximatePosition(getLeg().getFrom());
|
||||
final Position approximatePositionOfTo = markPositionCache.getApproximatePosition(getLeg().getTo());
|
||||
if (approximatePositionOfFrom != null && approximatePositionOfTo != null) {
|
||||
result = approximatePositionOfFrom.getDistance(approximatePositionOfTo);
|
||||
} else {
|
||||
@@ -349,6 +359,11 @@ public class TrackedLegImpl implements TrackedLeg {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getGreatCircleDistance(TimePoint timePoint) {
|
||||
return getGreatCircleDistance(timePoint, new NonCachingMarkPositionAtTimePointCache(getTrackedRace(), timePoint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getAbsoluteWindwardDistance(Position pos1, Position pos2, TimePoint at, WindPositionMode windPositionMode) {
|
||||
return getAbsoluteWindwardDistance(pos1, pos2, at, windPositionMode, new LeaderboardDTOCalculationReuseCache(at));
|
||||
@@ -498,8 +513,10 @@ public class TrackedLegImpl implements TrackedLeg {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration getEstimatedTimeToComplete(PolarDataService polarDataService, TimePoint timepoint)
|
||||
public Duration getEstimatedTimeToComplete(PolarDataService polarDataService, TimePoint timepoint, MarkPositionAtTimePointCache markPositionCache)
|
||||
throws NotEnoughDataHasBeenAddedException, NoWindException {
|
||||
assert timepoint.equals(markPositionCache.getTimePoint());
|
||||
assert getTrackedRace() == markPositionCache.getTrackedRace();
|
||||
Position centralPosition = trackedRace.getCenterOfCourse(timepoint);
|
||||
Wind wind = trackedRace.getWind(centralPosition, timepoint, getTrackedRace().getWindSources(WindSourceType.TRACK_BASED_ESTIMATION));
|
||||
Position from = trackedRace.getApproximatePosition(leg.getFrom(), timepoint);
|
||||
|
||||
+10
-5
@@ -127,6 +127,7 @@ import com.sap.sailing.domain.tracking.GPSTrackListener;
|
||||
import com.sap.sailing.domain.tracking.LineDetails;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
|
||||
import com.sap.sailing.domain.tracking.RaceChangeListener;
|
||||
import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider;
|
||||
import com.sap.sailing.domain.tracking.RaceListener;
|
||||
@@ -158,6 +159,7 @@ import com.sap.sse.util.SmartFutureCache;
|
||||
import com.sap.sse.util.SmartFutureCache.AbstractCacheUpdater;
|
||||
import com.sap.sse.util.SmartFutureCache.EmptyUpdateInterval;
|
||||
import com.sap.sse.util.impl.ArrayListNavigableSet;
|
||||
import com.sap.sse.util.impl.FutureTaskWithTracingGet;
|
||||
|
||||
import difflib.DiffUtils;
|
||||
import difflib.Patch;
|
||||
@@ -750,7 +752,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
/**
|
||||
* Monitor object to synchronize access to the {@link #updateStartAndEndOfTracking(boolean)} method. See bug 3922.
|
||||
*/
|
||||
private final Serializable updateStartAndEndOfTrackingMonitor = "";
|
||||
private final Serializable updateStartAndEndOfTrackingMonitor = "updateStartAndEndOfTrackingMonitor";
|
||||
|
||||
/**
|
||||
* Updates the start and end of tracking in the following precedence order:
|
||||
@@ -1670,10 +1672,12 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint) {
|
||||
public Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint, MarkPositionAtTimePointCache markPositionCache) {
|
||||
assert timePoint.equals(markPositionCache.getTimePoint());
|
||||
assert this == markPositionCache.getTrackedRace();
|
||||
Position result = null;
|
||||
for (Mark mark : waypoint.getMarks()) {
|
||||
Position nextPos = getOrCreateTrack(mark).getEstimatedPosition(timePoint, /* extrapolate */false);
|
||||
Position nextPos = markPositionCache.getEstimatedPosition(mark);
|
||||
if (result == null) {
|
||||
result = nextPos;
|
||||
} else if (nextPos != null) {
|
||||
@@ -1875,7 +1879,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
synchronized (directionFromStartToNextMarkCache) {
|
||||
future = directionFromStartToNextMarkCache.get(at);
|
||||
if (future == null) {
|
||||
newFuture = new FutureTask<Wind>(new Callable<Wind>() {
|
||||
newFuture = new FutureTaskWithTracingGet<Wind>("getDirectionFromStartToNextMark for "+this, new Callable<Wind>() {
|
||||
@Override
|
||||
public Wind call() {
|
||||
Wind result;
|
||||
@@ -3892,8 +3896,9 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
throw new NotEnoughDataHasBeenAddedException("Target time estimation failed. No polar service available.");
|
||||
}
|
||||
Duration durationOfAllLegs = Duration.NULL;
|
||||
final MarkPositionAtTimePointCache markPositionCache = new MarkPositionAtTimePointCacheImpl(this, timepoint);
|
||||
for (TrackedLeg leg : trackedLegs.values()) {
|
||||
Duration durationOfLeg = leg.getEstimatedTimeToComplete(polarDataService, timepoint);
|
||||
Duration durationOfLeg = leg.getEstimatedTimeToComplete(polarDataService, timepoint, markPositionCache);
|
||||
durationOfAllLegs = durationOfAllLegs.plus(durationOfLeg);
|
||||
}
|
||||
return durationOfAllLegs;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.sap.sailing.util;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.impl.MeterDistance;
|
||||
|
||||
public class RegattaUtil {
|
||||
|
||||
public static final Distance DEFAULT_BUOY_ZONE_RADIUS = new MeterDistance(15);
|
||||
|
||||
public static Distance getCalculatedRegattaBuoyZoneRadius(Regatta regatta, BoatClass boatClass) {
|
||||
final double buoyZoneRadiusInHullLengths;
|
||||
if (regatta != null && regatta.getBuoyZoneRadiusInHullLengths() != null) {
|
||||
buoyZoneRadiusInHullLengths = regatta.getBuoyZoneRadiusInHullLengths();
|
||||
} else {
|
||||
buoyZoneRadiusInHullLengths = Regatta.DEFAULT_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS;
|
||||
}
|
||||
final Distance boatHullLength = boatClass == null ? null : boatClass.getHullLength();
|
||||
final Distance buyZoneRadius = boatHullLength == null ? DEFAULT_BUOY_ZONE_RADIUS
|
||||
: boatHullLength.scale(buoyZoneRadiusInHullLengths);
|
||||
return buyZoneRadius;
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -50,6 +50,7 @@ import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.LineDetails;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
|
||||
import com.sap.sailing.domain.tracking.RaceAbortedListener;
|
||||
import com.sap.sailing.domain.tracking.RaceChangeListener;
|
||||
import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider;
|
||||
@@ -352,7 +353,7 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint) {
|
||||
public Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint, MarkPositionAtTimePointCache markPositionCache) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ public class PingMarkViaRegattaLogTest {
|
||||
Collections.singletonList(columnName), service);
|
||||
Regatta regatta = service.createRegatta(RegattaImpl.getDefaultName("regatta", "Laser"), "Laser", /*startDate*/ null, /*endDate*/ null,
|
||||
UUID.randomUUID(), Collections.<Series>singletonList(series),
|
||||
false, new HighPoint(), UUID.randomUUID(), /* useStartTimeInference */ true,
|
||||
false, new HighPoint(), UUID.randomUUID(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true,
|
||||
/* controlTrackingFromStartAndFinishTimes */ false, RankingMetricsFactory.getRankingMetricConstructor(RankingMetrics.ONE_DESIGN));
|
||||
RegattaLeaderboard leaderboard = service.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "RegattaLeaderboard", new int[] {});
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
<!-- Any title is fine -->
|
||||
<!-- -->
|
||||
<title>SAP Sailing Analytics AutoPlay</title>
|
||||
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-reset-2.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-normalize-3.0.2.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="LeaderboardNewHome.css">
|
||||
|
||||
@@ -1,256 +1,260 @@
|
||||
/** Add css rules here for your application. */
|
||||
/*
|
||||
body #calendar:after
|
||||
content: " ";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
*/
|
||||
.clearafter {
|
||||
clear: both;
|
||||
font-size: 1px;
|
||||
height: 0px;
|
||||
line-height: 0px;
|
||||
margin: -1px 0 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cover {
|
||||
left: -1000px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: -1000px;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
background: url(images/spectatorview-bg.png) no-repeat left top #ebebeb;
|
||||
font-family: 'Open Sans', Arial, Verdana, sans-serif;
|
||||
line-height: 1;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
padding: 85px 0 0 0;
|
||||
margin: 0;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #2968c0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
table td,select,button {
|
||||
line-height: 1;
|
||||
font-family: 'Open Sans', Arial, Verdana, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.gwt-DialogBox {
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.gwt-ToggleButton {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.gwt-PopupPanelGlass {
|
||||
z-index: 19;
|
||||
}
|
||||
|
||||
.contentOuterPanel {
|
||||
background: #dddcdc;
|
||||
margin: 0 12px 0 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/** Example rules used by the template application (remove for your app) */
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
color: #777777;
|
||||
margin: 40px 0px 70px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: separate;
|
||||
}
|
||||
|
||||
.LogoAndTitlePanel {
|
||||
height: 68px;
|
||||
font-family: Arial, Verdana, sans-serif;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
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;
|
||||
-o-box-shadow: 0 0 20px #858585;
|
||||
-ms-box-shadow: 0 0 20px #858585;
|
||||
}
|
||||
|
||||
.LogoAndTitlePanel:after {
|
||||
content: " ";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.RaceBoardHeaderPanel {
|
||||
margin: 0 12px 18px 12px;
|
||||
}
|
||||
|
||||
.sapLogo {
|
||||
float: left;
|
||||
margin: 13px 0 0 12px;
|
||||
}
|
||||
|
||||
.sailingAnalyticsLabelPanel {
|
||||
margin: 10px 0 0 0;
|
||||
}
|
||||
|
||||
.sailingAnalyticsLabel {
|
||||
float: left;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin: 15px 0 0 0;
|
||||
}
|
||||
|
||||
.leaderboardLabel {
|
||||
border-bottom: 2px solid #007dc0;
|
||||
font-weight: bold;
|
||||
padding: 0 0 6px 0;
|
||||
}
|
||||
|
||||
.refreshAndSettings {
|
||||
background: #f2f2f2;
|
||||
border-bottom: 2px solid #fff;
|
||||
border-top: 2px solid #fff;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.refreshAndSettings table td {
|
||||
padding: 0 10px 0 0;
|
||||
}
|
||||
|
||||
.refreshAndSettings table table td {
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
|
||||
.race-name {
|
||||
margin: 2px 10px 0 0;
|
||||
line-height: 1.0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
input.magnifier {
|
||||
display: block;
|
||||
margin: 3px auto 0 auto !important;
|
||||
}
|
||||
|
||||
.footerShadowPanel {
|
||||
position: fixed;
|
||||
height: 50px;
|
||||
bottom: 0;
|
||||
background: url(images/footer_shadow.png) left bottom repeat-x;
|
||||
width: 100%;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.mainPanel {
|
||||
width: 100%;
|
||||
margin-left: 13px;
|
||||
}
|
||||
|
||||
.errorLabel {
|
||||
color: #FF0000;
|
||||
}
|
||||
|
||||
.chart-importantMessage {
|
||||
font-family: 'Open Sans',Arial,Verdana,sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
height: 70px;
|
||||
margin: 0 auto;
|
||||
padding: 49px 0 0 80px;
|
||||
width: 400px;
|
||||
color: #7c7c7c;
|
||||
background: url(images/important-message.png) left center no-repeat;
|
||||
}
|
||||
|
||||
.chart-busyMessage {
|
||||
font-family: 'Open Sans',Arial,Verdana,sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
height: 70px;
|
||||
margin: 0 auto;
|
||||
padding: 49px 0 0 40px;
|
||||
width: 400px;
|
||||
color: #7c7c7c;
|
||||
background: url(images/busy_indicator_circle.gif) left center no-repeat;
|
||||
}
|
||||
|
||||
.dataMiningPanel {
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.dataMiningPanel-filledElement {
|
||||
background: url("images/btn-cta-orangeleft.png") repeat-x scroll center 0 transparent;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-top-left-radius: 3px;
|
||||
color: #FFFFFF;
|
||||
cursor: pointer;
|
||||
font-family: 'Open Sans',Verdana,Arial,sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
margin: 0 0 0 0;
|
||||
padding: 2px 7px 2px 3px;
|
||||
height: 18px;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
-moz-border-radius: 5px 0 0 5px;
|
||||
-webkit-border-radius: 5px 0 0 5px;
|
||||
-o-border-radius: 5px 0 0 5px;
|
||||
-ms-border-radius: 5px 0 0 5px;
|
||||
border-radius: 5px 0 0 5px;
|
||||
-moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||
-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||
-o-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||
-ms-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||
text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.settingsAnchor {
|
||||
position: relative;
|
||||
top: 9px;
|
||||
}
|
||||
|
||||
.groupingProviderElement {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.statisticProviderElement {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.definitionProviderControls {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.definitionProviderControlsElements {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.queryDefinitionViewerContent {
|
||||
background-color: white;
|
||||
padding: 5px;
|
||||
/** Add css rules here for your application. */
|
||||
/*
|
||||
body #calendar:after
|
||||
content: " ";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
*/
|
||||
html {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.clearafter {
|
||||
clear: both;
|
||||
font-size: 1px;
|
||||
height: 0px;
|
||||
line-height: 0px;
|
||||
margin: -1px 0 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cover {
|
||||
left: -1000px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: -1000px;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
background: url(images/spectatorview-bg.png) no-repeat left top #ebebeb;
|
||||
font-family: 'Open Sans', Arial, Verdana, sans-serif;
|
||||
line-height: 1;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
padding: 85px 0 0 0;
|
||||
margin: 0;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #2968c0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
table td,select,button {
|
||||
line-height: 1;
|
||||
font-family: 'Open Sans', Arial, Verdana, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.gwt-DialogBox {
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.gwt-ToggleButton {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.gwt-PopupPanelGlass {
|
||||
z-index: 19;
|
||||
}
|
||||
|
||||
.contentOuterPanel {
|
||||
background: #dddcdc;
|
||||
margin: 0 12px 0 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/** Example rules used by the template application (remove for your app) */
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
color: #777777;
|
||||
margin: 40px 0px 70px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: separate;
|
||||
}
|
||||
|
||||
.LogoAndTitlePanel {
|
||||
height: 68px;
|
||||
font-family: Arial, Verdana, sans-serif;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
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;
|
||||
-o-box-shadow: 0 0 20px #858585;
|
||||
-ms-box-shadow: 0 0 20px #858585;
|
||||
}
|
||||
|
||||
.LogoAndTitlePanel:after {
|
||||
content: " ";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.RaceBoardHeaderPanel {
|
||||
margin: 0 12px 18px 12px;
|
||||
}
|
||||
|
||||
.sapLogo {
|
||||
float: left;
|
||||
margin: 13px 0 0 12px;
|
||||
}
|
||||
|
||||
.sailingAnalyticsLabelPanel {
|
||||
margin: 10px 0 0 0;
|
||||
}
|
||||
|
||||
.sailingAnalyticsLabel {
|
||||
float: left;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin: 15px 0 0 0;
|
||||
}
|
||||
|
||||
.leaderboardLabel {
|
||||
border-bottom: 2px solid #007dc0;
|
||||
font-weight: bold;
|
||||
padding: 0 0 6px 0;
|
||||
}
|
||||
|
||||
.refreshAndSettings {
|
||||
background: #f2f2f2;
|
||||
border-bottom: 2px solid #fff;
|
||||
border-top: 2px solid #fff;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.refreshAndSettings table td {
|
||||
padding: 0 10px 0 0;
|
||||
}
|
||||
|
||||
.refreshAndSettings table table td {
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
|
||||
.race-name {
|
||||
margin: 2px 10px 0 0;
|
||||
line-height: 1.0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
input.magnifier {
|
||||
display: block;
|
||||
margin: 3px auto 0 auto !important;
|
||||
}
|
||||
|
||||
.footerShadowPanel {
|
||||
position: fixed;
|
||||
height: 50px;
|
||||
bottom: 0;
|
||||
background: url(images/footer_shadow.png) left bottom repeat-x;
|
||||
width: 100%;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.mainPanel {
|
||||
width: 100%;
|
||||
margin-left: 13px;
|
||||
}
|
||||
|
||||
.errorLabel {
|
||||
color: #FF0000;
|
||||
}
|
||||
|
||||
.chart-importantMessage {
|
||||
font-family: 'Open Sans',Arial,Verdana,sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
height: 70px;
|
||||
margin: 0 auto;
|
||||
padding: 49px 0 0 80px;
|
||||
width: 400px;
|
||||
color: #7c7c7c;
|
||||
background: url(images/important-message.png) left center no-repeat;
|
||||
}
|
||||
|
||||
.chart-busyMessage {
|
||||
font-family: 'Open Sans',Arial,Verdana,sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
height: 70px;
|
||||
margin: 0 auto;
|
||||
padding: 49px 0 0 40px;
|
||||
width: 400px;
|
||||
color: #7c7c7c;
|
||||
background: url(images/busy_indicator_circle.gif) left center no-repeat;
|
||||
}
|
||||
|
||||
.dataMiningPanel {
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.dataMiningPanel-filledElement {
|
||||
background: url("images/btn-cta-orangeleft.png") repeat-x scroll center 0 transparent;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-top-left-radius: 3px;
|
||||
color: #FFFFFF;
|
||||
cursor: pointer;
|
||||
font-family: 'Open Sans',Verdana,Arial,sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
margin: 0 0 0 0;
|
||||
padding: 2px 7px 2px 3px;
|
||||
height: 18px;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
-moz-border-radius: 5px 0 0 5px;
|
||||
-webkit-border-radius: 5px 0 0 5px;
|
||||
-o-border-radius: 5px 0 0 5px;
|
||||
-ms-border-radius: 5px 0 0 5px;
|
||||
border-radius: 5px 0 0 5px;
|
||||
-moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||
-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||
-o-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||
-ms-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||
text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.settingsAnchor {
|
||||
position: relative;
|
||||
top: 9px;
|
||||
}
|
||||
|
||||
.groupingProviderElement {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.statisticProviderElement {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.definitionProviderControls {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.definitionProviderControlsElements {
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.queryDefinitionViewerContent {
|
||||
background-color: white;
|
||||
padding: 5px;
|
||||
}
|
||||
@@ -5,9 +5,7 @@ table {
|
||||
}
|
||||
|
||||
.leaderboardContent td, .leaderboardContent th {
|
||||
vertical-align: bottom;
|
||||
line-height: 1.3;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.leaderboardContent-toolbar {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill=
|
||||
"#FFF" d="M10,2a8,8,0,1,1-8,8,8,8,0,0,1,8-8m0-2A10,10,0,1,0,20,10,10,10,0,0,0,
|
||||
10,0h0ZM9.71,10l0.08,0L9.71,10V10m-2-3.43v7l3.07-1.74L13.86,10,10.78,8.26,7.71,
|
||||
6.52h0Z"/></svg>
|
||||
|
After Width: | Height: | Size: 252 B |
+3
-4
@@ -28,6 +28,7 @@ import com.sap.sailing.gwt.autoplay.client.place.player.AutoPlayerConfiguration;
|
||||
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspectiveLifecycle;
|
||||
import com.sap.sailing.gwt.autoplay.client.shared.leaderboard.LeaderboardWithHeaderPerspectiveSettings;
|
||||
import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication;
|
||||
import com.sap.sailing.gwt.common.authentication.SAPSailingHeaderWithAuthentication;
|
||||
import com.sap.sailing.gwt.common.client.SharedResources;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPerspectiveLifecycle;
|
||||
@@ -44,7 +45,6 @@ import com.sap.sse.gwt.client.shared.perspective.PerspectiveCompositeLifecycleTa
|
||||
import com.sap.sse.gwt.client.shared.perspective.PerspectiveCompositeSettings;
|
||||
import com.sap.sse.gwt.client.shared.perspective.PerspectiveLifecycle;
|
||||
import com.sap.sse.gwt.client.shared.perspective.PerspectiveLifecycleWithAllSettings;
|
||||
import com.sap.sse.security.ui.authentication.generic.sapheader.SAPHeaderWithAuthentication;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
|
||||
public class DesktopStartView extends Composite implements StartView {
|
||||
@@ -53,7 +53,7 @@ public class DesktopStartView extends Composite implements StartView {
|
||||
interface StartPageViewUiBinder extends UiBinder<Widget, DesktopStartView> {
|
||||
}
|
||||
|
||||
@UiField(provided=true) SAPHeaderWithAuthentication sapHeader;
|
||||
@UiField(provided=true) SAPSailingHeaderWithAuthentication sapHeader;
|
||||
@UiField(provided=true) ListBox localeSelectionBox;
|
||||
@UiField(provided=true) ListBox eventSelectionBox;
|
||||
@UiField(provided=true) ListBox leaderboardSelectionBox;
|
||||
@@ -82,8 +82,7 @@ public class DesktopStartView extends Composite implements StartView {
|
||||
this.eventBus = eventBus;
|
||||
this.events = new ArrayList<EventDTO>();
|
||||
|
||||
sapHeader = new SAPHeaderWithAuthentication(StringMessages.INSTANCE.sapSailingAnalytics(),
|
||||
StringMessages.INSTANCE.autoplayConfiguration());
|
||||
sapHeader = new SAPSailingHeaderWithAuthentication(StringMessages.INSTANCE.autoplayConfiguration());
|
||||
new FixedSailingAuthentication(userService, sapHeader.getAuthenticationMenuView());
|
||||
|
||||
eventSelectionBox = new ListBox();
|
||||
|
||||
+3
-3
@@ -4,23 +4,23 @@ import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication;
|
||||
import com.sap.sailing.gwt.common.authentication.SAPSailingHeaderWithAuthentication;
|
||||
import com.sap.sailing.gwt.common.client.FullscreenUtil;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.gwt.client.shared.components.AbstractCompositeComponent;
|
||||
import com.sap.sse.security.ui.authentication.generic.sapheader.SAPHeaderWithAuthentication;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
|
||||
public class SAPHeaderComponent extends AbstractCompositeComponent<SAPHeaderComponentSettings> {
|
||||
private SAPHeaderComponentSettings settings;
|
||||
private final SAPHeaderComponentLifecycle componentLifecycle;
|
||||
|
||||
private final SAPHeaderWithAuthentication sapHeader;
|
||||
private final SAPSailingHeaderWithAuthentication sapHeader;
|
||||
|
||||
public SAPHeaderComponent(SAPHeaderComponentLifecycle componentLifecycle, UserService userService, SAPHeaderComponentSettings settings,
|
||||
StringMessages stringMessages, boolean startInAutoScreenMode) {
|
||||
this.componentLifecycle = componentLifecycle;
|
||||
this.settings = settings;
|
||||
this.sapHeader = new SAPHeaderWithAuthentication(stringMessages.sapSailingAnalytics(), settings.getTitle());
|
||||
this.sapHeader = new SAPSailingHeaderWithAuthentication(settings.getTitle());
|
||||
new FixedSailingAuthentication(userService, sapHeader.getAuthenticationMenuView());
|
||||
|
||||
initWidget(sapHeader);
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.sap.sailing.gwt.common.authentication;
|
||||
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.security.ui.authentication.generic.sapheader.SAPHeaderWithAuthentication;
|
||||
|
||||
public class SAPSailingHeaderWithAuthentication extends SAPHeaderWithAuthentication {
|
||||
|
||||
private static final String SAP_SAILING_URL = "http://www.sapsailing.com";
|
||||
private static final String SAP_SAILING_APP_NAME = StringMessages.INSTANCE.sapSailingAnalytics();
|
||||
|
||||
|
||||
public SAPSailingHeaderWithAuthentication() {
|
||||
super(SAP_SAILING_APP_NAME, SAP_SAILING_URL);
|
||||
}
|
||||
|
||||
public SAPSailingHeaderWithAuthentication(String headerText) {
|
||||
super(SAP_SAILING_APP_NAME, SAP_SAILING_URL, headerText);
|
||||
}
|
||||
|
||||
}
|
||||
+11
-1
@@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sse.gwt.dispatch.shared.commands.DTO;
|
||||
|
||||
public class RegattaMetadataDTO extends RegattaReferenceDTO implements HasRegattaMetadata {
|
||||
@@ -18,6 +19,7 @@ public class RegattaMetadataDTO extends RegattaReferenceDTO implements HasRegatt
|
||||
private RegattaState state;
|
||||
private boolean flexibleLeaderboard;
|
||||
private RaceDataInfo raceDataInfo;
|
||||
private Distance buoyZoneRadius;
|
||||
|
||||
public RegattaMetadataDTO() {
|
||||
}
|
||||
@@ -122,7 +124,15 @@ public class RegattaMetadataDTO extends RegattaReferenceDTO implements HasRegatt
|
||||
public void setRaceDataInfo(RaceDataInfo raceDataInfo) {
|
||||
this.raceDataInfo = raceDataInfo;
|
||||
}
|
||||
|
||||
|
||||
public Distance getBuoyZoneRadius() {
|
||||
return buoyZoneRadius;
|
||||
}
|
||||
|
||||
public void setBuoyZoneRadius(Distance buoyZoneRadius) {
|
||||
this.buoyZoneRadius = buoyZoneRadius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holder class for flags, which inform about GPS, wind, video or audio data availability.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ public class GetFavoritesAction implements SailingAction<FavoritesResult> {
|
||||
if (preferences != null) {
|
||||
for (BoatClassNotificationPreference pref : preferences.getBoatClasses()) {
|
||||
String name = pref.getBoatClass().getName(), displayName = pref.getBoatClass().getDisplayName();
|
||||
selected.add(new BoatClassDTO(name, displayName, pref.getBoatClass().getHullLength().getMeters()));
|
||||
selected.add(new BoatClassDTO(name, displayName, pref.getBoatClass().getHullLength()));
|
||||
notifyAboutUpcomingRaces |= pref.isNotifyAboutUpcomingRaces();
|
||||
notifyAboutResults |= pref.isNotifyAboutResults();
|
||||
}
|
||||
|
||||
+13
-13
@@ -1,14 +1,14 @@
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
|
||||
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared"
|
||||
xmlns:dp="urn:import:com.sap.sailing.gwt.home.desktop.partials">
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.racelist.RaceListResources" />
|
||||
<g:HTMLPanel addStyleNames="{local_res.css.raceslistlive}">
|
||||
<h3 ui:field="titleUi"></h3>
|
||||
<div style="display: none;" ui:field="infoUi"></div>
|
||||
<div style="display: none; font-weight: bold; font-style: italic;" ui:field="noContentPlaceholderUi"></div>
|
||||
<dp:racelist.AbstractRaceList ui:field="raceListUi"/>
|
||||
</g:HTMLPanel>
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
|
||||
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared"
|
||||
xmlns:dp="urn:import:com.sap.sailing.gwt.home.desktop.partials">
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.racelist.RaceListResources" />
|
||||
<g:HTMLPanel addStyleNames="{local_res.css.raceslistlive}">
|
||||
<h3 ui:field="titleUi"></h3>
|
||||
<div style="display: none;" ui:field="infoUi"></div>
|
||||
<div style="display: none; font-weight: bold; font-style: italic;" ui:field="noContentPlaceholderUi"></div>
|
||||
<dp:racelist.AbstractRaceList ui:field="raceListUi"/>
|
||||
</g:HTMLPanel>
|
||||
</ui:UiBinder>
|
||||
+19
@@ -63,6 +63,7 @@
|
||||
.raceviewerlaunchpad:hover {
|
||||
cursor: pointer;
|
||||
background: #0081b8;
|
||||
text-decoration: none;
|
||||
}
|
||||
.raceviewerlaunchpadlive {
|
||||
background: #e94a1b;
|
||||
@@ -79,11 +80,29 @@
|
||||
.raceviewerlaunchpadlive .raceviewerlaunchpad_content_item_icon svg {
|
||||
fill: #e94a1b;
|
||||
}
|
||||
.raceviewerlaunchpadplanned {
|
||||
background: #999999;
|
||||
}
|
||||
.raceviewerlaunchpadplanned:hover {
|
||||
background: #8a8a8a;
|
||||
}
|
||||
.raceviewerlaunchpadplanned .raceviewerlaunchpad_content_item {
|
||||
color: #999999;
|
||||
}
|
||||
.raceviewerlaunchpadplanned .raceviewerlaunchpad_content_item:hover {
|
||||
background: #999999;
|
||||
}
|
||||
.raceviewerlaunchpadplanned .raceviewerlaunchpad_content_item_icon svg {
|
||||
fill: #999999;
|
||||
}
|
||||
.raceviewerlaunchpad_icon {
|
||||
margin-left: 0.666666666666667em;
|
||||
width: 1.666666666666667em;
|
||||
height: 1.333333333333333em;
|
||||
}
|
||||
.raceviewerlaunchpad_icon img {
|
||||
height: 100%;
|
||||
}
|
||||
.raceviewerlaunchpad_icon svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
+109
-84
@@ -1,85 +1,110 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.raceviewerlaunchpad;
|
||||
|
||||
import com.google.gwt.cell.client.AbstractCell;
|
||||
import com.google.gwt.cell.client.ValueUpdater;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.BrowserEvents;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.dom.client.NativeEvent;
|
||||
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
|
||||
import com.google.gwt.safehtml.shared.SafeHtml;
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.PopupPanel;
|
||||
import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
|
||||
import com.sap.sailing.gwt.home.communication.race.RaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.desktop.places.event.EventView;
|
||||
import com.sap.sailing.gwt.home.desktop.places.event.EventView.Presenter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class RaceviewerLaunchPadCell<T extends RaceMetadataDTO<?>> extends AbstractCell<T> {
|
||||
|
||||
interface CellTemplates extends SafeHtmlTemplates {
|
||||
@Template("<div class=\"{0}\">{1}</div>")
|
||||
SafeHtml raceNotTracked(String styleNames, String text);
|
||||
|
||||
@Template("<div class=\"{0}\"><div>{2}</div><div class=\"{1}\"><img src=\"images/home/launch-loupe.svg\"/></div>")
|
||||
SafeHtml raceviewerLaunchPad(String styleNames, String iconStyleNames, String text);
|
||||
}
|
||||
|
||||
private static final CellTemplates TEMPLATE = GWT.create(CellTemplates.class);
|
||||
private static final StringMessages I18N = StringMessages.INSTANCE;
|
||||
|
||||
private final RaceviewerLaunchPadResources local_res = RaceviewerLaunchPadResources.INSTANCE;
|
||||
private final String notTrackedStyleNames = local_res.css().raceviewerlaunchpad_not_tracked();
|
||||
private final String analyzeStyleNames = local_res.css().raceviewerlaunchpad();
|
||||
private final String liveStyleNames = Util.join(" ", analyzeStyleNames, local_res.css().raceviewerlaunchpadlive());
|
||||
private final String iconStyleNames = local_res.css().raceviewerlaunchpad_icon();
|
||||
|
||||
private final EventView.Presenter presenter;
|
||||
private final PopupPanel panel = new PopupPanel(true, false);
|
||||
|
||||
public RaceviewerLaunchPadCell(Presenter presenter) {
|
||||
super(BrowserEvents.CLICK);
|
||||
local_res.css().ensureInjected();
|
||||
this.presenter = presenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBrowserEvent(Context context, final Element parent, T data, NativeEvent event,
|
||||
ValueUpdater<T> valueUpdater) {
|
||||
if (data.hasValidTrackingData() && BrowserEvents.CLICK.equals(event.getType())
|
||||
&& parent.getFirstChildElement().isOrHasChild(Element.as(event.getEventTarget()))) {
|
||||
panel.setWidget(new RaceviewerLaunchPad(data, panel) {
|
||||
@Override
|
||||
protected String getRaceViewerURL(SimpleRaceMetadataDTO data, String mode) {
|
||||
return presenter.getRaceViewerURL(data, mode);
|
||||
}
|
||||
});
|
||||
panel.setPopupPositionAndShow(new PositionCallback() {
|
||||
@Override
|
||||
public void setPosition(int offsetWidth, int offsetHeight) {
|
||||
int alignBottom = parent.getAbsoluteTop() + parent.getOffsetHeight() - offsetHeight;
|
||||
int top = (alignBottom - Window.getScrollTop() < 0 ? parent.getAbsoluteTop() - 1 : alignBottom + 1);
|
||||
panel.setPopupPosition(parent.getAbsoluteRight() + 1 - offsetWidth, top);
|
||||
panel.getElement().scrollIntoView();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
super.onBrowserEvent(context, parent, data, event, valueUpdater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Context context, T data, SafeHtmlBuilder sb) {
|
||||
if (data.hasValidTrackingData()) {
|
||||
String styleNames = data.isFinished() ? analyzeStyleNames : liveStyleNames;
|
||||
sb.append(TEMPLATE.raceviewerLaunchPad(styleNames, iconStyleNames, I18N.raceDetailsToShow()));
|
||||
} else {
|
||||
package com.sap.sailing.gwt.home.desktop.partials.raceviewerlaunchpad;
|
||||
|
||||
import com.google.gwt.cell.client.AbstractCell;
|
||||
import com.google.gwt.cell.client.ValueUpdater;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.BrowserEvents;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.dom.client.NativeEvent;
|
||||
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
|
||||
import com.google.gwt.safehtml.shared.SafeHtml;
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.PopupPanel;
|
||||
import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
|
||||
import com.sap.sailing.gwt.home.communication.race.RaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO;
|
||||
import com.sap.sailing.gwt.home.desktop.places.event.EventView;
|
||||
import com.sap.sailing.gwt.home.desktop.places.event.EventView.Presenter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.raceboard.RaceBoardModes;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class RaceviewerLaunchPadCell<T extends RaceMetadataDTO<?>> extends AbstractCell<T> {
|
||||
|
||||
interface CellTemplates extends SafeHtmlTemplates {
|
||||
@Template("<div class=\"{0}\">{1}</div>")
|
||||
SafeHtml raceNotTracked(String styleNames, String text);
|
||||
|
||||
@Template("<div class=\"{0}\"><div>{2}</div><div class=\"{1}\"><img src=\"images/home/launch-loupe.svg\"/></div>")
|
||||
SafeHtml raceviewerLaunchPad(String styleNames, String iconStyleNames, String text);
|
||||
|
||||
@Template("<a href=\"{4}\" target=\"_blank\" class=\"{0}\"><div>{2}</div><div class=\"{1}\"><img src=\"images/home/{3}.svg\"/></div></a> ")
|
||||
SafeHtml standaloneButton(String styleNames, String iconStyleNames, String text, String icon, String link);
|
||||
}
|
||||
|
||||
private static final CellTemplates TEMPLATE = GWT.create(CellTemplates.class);
|
||||
private static final StringMessages I18N = StringMessages.INSTANCE;
|
||||
|
||||
private final RaceviewerLaunchPadResources local_res = RaceviewerLaunchPadResources.INSTANCE;
|
||||
private final String notTrackedStyleNames = local_res.css().raceviewerlaunchpad_not_tracked();
|
||||
private final String analyzeStyleNames = local_res.css().raceviewerlaunchpad();
|
||||
private final String plannedStyleNames = Util.join(" ", analyzeStyleNames, local_res.css().raceviewerlaunchpadplanned());
|
||||
private final String liveStyleNames = Util.join(" ", analyzeStyleNames, local_res.css().raceviewerlaunchpadlive());
|
||||
private final String iconStyleNames = local_res.css().raceviewerlaunchpad_icon();
|
||||
|
||||
private final EventView.Presenter presenter;
|
||||
private final PopupPanel panel = new PopupPanel(true, false);
|
||||
|
||||
public RaceviewerLaunchPadCell(Presenter presenter) {
|
||||
super(BrowserEvents.CLICK);
|
||||
local_res.css().ensureInjected();
|
||||
this.presenter = presenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBrowserEvent(Context context, final Element parent, T data, NativeEvent event,
|
||||
ValueUpdater<T> valueUpdater) {
|
||||
if (!renderAsDirectLinkButton(data)) {
|
||||
if (data.hasValidTrackingData() && BrowserEvents.CLICK.equals(event.getType())
|
||||
&& parent.getFirstChildElement().isOrHasChild(Element.as(event.getEventTarget()))) {
|
||||
panel.setWidget(createLaunchPad(parent.getFirstChildElement(), data));
|
||||
panel.setPopupPositionAndShow(new PositionCallback() {
|
||||
@Override
|
||||
public void setPosition(int offsetWidth, int offsetHeight) {
|
||||
int alignBottom = parent.getAbsoluteTop() + parent.getOffsetHeight() - offsetHeight;
|
||||
int top = (alignBottom - Window.getScrollTop() < 0 ? parent.getAbsoluteTop() - 1 : alignBottom + 1);
|
||||
panel.setPopupPosition(parent.getAbsoluteRight() + 1 - offsetWidth, top);
|
||||
panel.getElement().scrollIntoView();
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
super.onBrowserEvent(context, parent, data, event, valueUpdater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Context context, T data, SafeHtmlBuilder sb) {
|
||||
if (data.hasValidTrackingData()) {
|
||||
if (renderAsDirectLinkButton(data)) {
|
||||
sb.append(TEMPLATE.standaloneButton(plannedStyleNames, iconStyleNames, I18N.watchLive(),
|
||||
"launch-play", presenter.getRaceViewerURL(data, RaceBoardModes.PLAYER.name())));
|
||||
} else {
|
||||
String styleNames = data.isFinished() ? analyzeStyleNames : liveStyleNames;
|
||||
sb.append(TEMPLATE.raceviewerLaunchPad(styleNames, iconStyleNames, I18N.raceDetailsToShow()));
|
||||
}
|
||||
} else {
|
||||
sb.append(TEMPLATE.raceNotTracked(notTrackedStyleNames, I18N.eventRegattaRaceNotTracked()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link RaceviewerLaunchPad} for the given data object.
|
||||
*/
|
||||
private RaceviewerLaunchPad createLaunchPad(Element button, T data) {
|
||||
RaceviewerLaunchPad launchPad = new RaceviewerLaunchPad(data, panel) {
|
||||
@Override
|
||||
protected String getRaceViewerURL(SimpleRaceMetadataDTO data, String raceBoardMode) {
|
||||
return presenter.getRaceViewerURL(data, raceBoardMode);
|
||||
}
|
||||
};
|
||||
return launchPad;
|
||||
}
|
||||
|
||||
/** Determine whether a direct link button should be/is rendered instead of a menu popup. */
|
||||
private boolean renderAsDirectLinkButton(T data) {
|
||||
return !data.isFinished() && !data.isRunning();
|
||||
}
|
||||
|
||||
}
|
||||
+1
@@ -18,6 +18,7 @@ public interface RaceviewerLaunchPadResources extends ClientBundle {
|
||||
String raceviewerlaunchpad_date();
|
||||
String raceviewerlaunchpad_cta();
|
||||
String raceviewerlaunchpadlive();
|
||||
String raceviewerlaunchpadplanned();
|
||||
String raceviewerlaunchpad_content_item();
|
||||
String raceviewerlaunchpad_content_item_icon();
|
||||
String raceviewerlaunchpad_icon();
|
||||
|
||||
+3
@@ -174,6 +174,9 @@
|
||||
.fleet_races_raceplanned:hover {
|
||||
background-color: #8a8a8a;
|
||||
}
|
||||
.fleet_races_raceplanned .fleet_races_race_name:after {
|
||||
background: url("images/home/launch-play.svg") no-repeat center center;
|
||||
}
|
||||
.fleet_races_raceuntracked .fleet_races_race_name:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
Loaded 100 of 298 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user