diff --git a/icpc-live-v2.iml b/icpc-live-v2.iml
index fa82e70d..39156f56 100644
--- a/icpc-live-v2.iml
+++ b/icpc-live-v2.iml
@@ -27,6 +27,9 @@
+
+
+
diff --git a/src/main/java/ru/ifmo/acm/backend/Main.java b/src/main/java/ru/ifmo/acm/backend/Main.java
index 862a676d..b012147b 100644
--- a/src/main/java/ru/ifmo/acm/backend/Main.java
+++ b/src/main/java/ru/ifmo/acm/backend/Main.java
@@ -59,6 +59,16 @@ private void run() throws InterruptedException, InvocationTargetException, IOExc
generator.addWidget(new QueueWidget(100));
generator.addWidget(new BigStandingsWidget(64, 64,
Widget.BASE_WIDTH - 128, Widget.BASE_HEIGHT - 128, updateWait, true));
+ generator.addWidget(new BreakingNewsWidget(
+ updateWait,
+ (int)(Widget.BASE_WIDTH * 0.65),
+ (int)(Widget.BASE_HEIGHT * 0.6),
+ (int)(Widget.BASE_WIDTH * 0.3),
+ (int)(Widget.BASE_HEIGHT * 0.2),
+ 16. / 9,
+ Integer.parseInt(properties.getProperty("sleep.time")),
+ Integer.parseInt(properties.getProperty("breakingnews.time"))
+ ));
new TickPlayer("Main screen", generator, frameRate).frame.setLocation(0, 0);
}
diff --git a/src/main/java/ru/ifmo/acm/backend/player/widgets/BreakingNewsWidget.java b/src/main/java/ru/ifmo/acm/backend/player/widgets/BreakingNewsWidget.java
index b997e26c..f1ad22fc 100644
--- a/src/main/java/ru/ifmo/acm/backend/player/widgets/BreakingNewsWidget.java
+++ b/src/main/java/ru/ifmo/acm/backend/player/widgets/BreakingNewsWidget.java
@@ -19,12 +19,13 @@ public class BreakingNewsWidget extends VideoWidget {
private final int PLATE_WIDTH;
private final int GAP;
- public BreakingNewsWidget(int x, int y, int width, int height, double aspectRatio, int sleepTime, int duration) {
+ public BreakingNewsWidget(long updateWait, int x, int y, int width, int height, double aspectRatio, int sleepTime, int duration) {
super(x, y, width, (int) (height / aspectRatio), sleepTime, 0);
+ this.updateWait = updateWait;
wVideo = width;
- hVideo = (int) (height / aspectRatio);
+ hVideo = (int) (width / aspectRatio);
- PLATE_WIDTH = (int) (1.5 * width);
+ PLATE_WIDTH = (int) (1.2 * width);
GAP = (int) (0.05 * hVideo);
this.x = x;
@@ -52,13 +53,19 @@ protected void updateImpl(Data data) {
}
if (isVisible())
return;
- setVisible(true);
int teamId = data.breakingNewsData.teamId;
int problemId = data.breakingNewsData.problemId;
- team = Preparation.eventsLoader.getContestData().getParticipant(teamId).getSmallTeamInfo();
+ System.err.println("Get request for " + teamId + " " + problemId);
+
+ team = Preparation.eventsLoader.getContestData().getParticipant(teamId);
java.util.List runs = team.getRuns()[problemId];
+
+ if (runs.size() == 0) {
+ System.err.println("Team " + teamId + " has no submit for problem " + problemId);
+ return;
+ }
run = runs.get(runs.size() - 1);
for (RunInfo run1 : runs) {
if (run1.isAccepted()) {
@@ -70,9 +77,11 @@ protected void updateImpl(Data data) {
if (data.breakingNewsData.isLive) {
url = TeamWidget.getUrl(team, data.breakingNewsData.infoType);
} else {
- url = run.toString();
+ url = TeamWidget.getUrl(run);
}
+ System.err.println("Change to " + url);
+
change(url);
isLive = data.breakingNewsData.isLive;
@@ -89,37 +98,69 @@ protected void updateImpl(Data data) {
}
caption += " problem " + (char) ('A' + problemId);
+ System.err.println("Caption: " + caption);
+
currentShow = run.getTeamInfoBefore();
timer = 0;
+ rankState = 0;
+ visibilityState = 0;
+ setVisible(true);
}
lastUpdate = System.currentTimeMillis();
}
+ private double localVisibility;
+ private int rankState;
@Override
public void paintImpl(Graphics2D g, int width, int height) {
update();
- if (visibilityState == 0) {
+ int dt = updateVisibilityState();
+
+ if (visibilityState == 0 && !isVisible()) {
stop();
return;
}
- int dt = updateVisibilityState();
- timer += dt;
+ if (!ready.get()) {
+ return;
+ }
- if (timer > duration / 2) {
+ timer += dt;
+ System.err.println(localVisibility + " " + visibilityState + " " + isVisible());
+ if (rankState == 0) {
+ setVisibilityState(0);
+ rankState = 1;
+ }
+ if (timer > duration / 2 - 1000 && rankState == 1) {
+ rankState = 2;
+ localVisibility = 1;
+ }
+ if (rankState == 2) {
+ localVisibility -= dt * V;
+ localVisibility = Math.max(localVisibility, 0);
+ if (localVisibility == 0) {
+ rankState = 3;
+ }
+ }
+ if (rankState == 3) {
+ localVisibility += dt * V;
+ localVisibility = Math.min(localVisibility, 1);
currentShow = team;
+ if (localVisibility == 1) {
+ rankState = 4;
+ }
}
- if (run == null || URL.get() == null) {
+ if (run == null || URL.get() != null) {
int hh = (int) (hVideo * opacity);
g.drawImage(image.get(), x, y + (hVideo - hh) / 2, wVideo, hh, null);
}
int y = this.y + hVideo + GAP;
int x = this.x + (wVideo - PLATE_WIDTH) / 2;
- drawTeamPane(g, currentShow, x, y + hVideo, PLATE_WIDTH, visibilityState);
+ drawTeamPane(g, currentShow, x, y, PLATE_WIDTH, rankState == 2 || rankState == 3 ? localVisibility : visibilityState);
drawTextInRect(g, caption, (int) (x - 0.005 * PLATE_WIDTH), y, -1, PLATE_WIDTH / 10,
POSITION_RIGHT, ACCENT_COLOR, Color.white, visibilityState);
}
diff --git a/src/main/java/ru/ifmo/acm/backend/player/widgets/TeamWidget.java b/src/main/java/ru/ifmo/acm/backend/player/widgets/TeamWidget.java
index 7c15e0fc..835ea68e 100644
--- a/src/main/java/ru/ifmo/acm/backend/player/widgets/TeamWidget.java
+++ b/src/main/java/ru/ifmo/acm/backend/player/widgets/TeamWidget.java
@@ -27,6 +27,9 @@ public class TeamWidget extends VideoWidget {
String url = properties.getProperty("info." + types[i], "");
urlTemplates.put(types[i], url);
}
+ if (properties.get("info.record") != null) {
+ urlTemplates.put("record", properties.getProperty("info.record"));
+ }
} catch (Exception e) {
e.printStackTrace();
}
@@ -195,4 +198,8 @@ public static String getUrl(TeamInfo team, String infoType) {
}
return null;
}
+
+ public static String getUrl(RunInfo run) {
+ return String.format(urlTemplates.get("record"), run.getId());
+ }
}
diff --git a/src/main/java/ru/ifmo/acm/backend/player/widgets/Widget.java b/src/main/java/ru/ifmo/acm/backend/player/widgets/Widget.java
index e0613545..3608cdc6 100644
--- a/src/main/java/ru/ifmo/acm/backend/player/widgets/Widget.java
+++ b/src/main/java/ru/ifmo/acm/backend/player/widgets/Widget.java
@@ -75,7 +75,7 @@ public void paint(Graphics2D g, int width, int height, double scale) {
}
}
- private static final double V = 0.001;
+ protected static final double V = 0.001;
protected int updateVisibilityState() {
long time = System.currentTimeMillis();
@@ -98,6 +98,14 @@ public void setVisibilityState(double visibilityState) {
textOpacity = f(visibilityState * 2 - 1);
}
+ public double getOpacity(double visibilityState) {
+ return f(visibilityState * 2);
+ }
+
+ public double getTextOpacity(double visibilityState) {
+ return f(visibilityState * 2 - 1);
+ }
+
protected double f(double x) {
if (x < 0) return 0;
if (x > 1) return 1;
@@ -146,8 +154,10 @@ void drawRect(Graphics2D g, int x, int y, int width, int height, Color color, do
static final int POSITION_RIGHT = 1;
static final int POSITION_CENTER = 2;
- void drawTextInRect(Graphics2D g, String text, int x, int y, int width, int height, int position, Color color, Color textColor, double state) {
- setVisibilityState(state);
+ void drawTextInRect(Graphics2D g, String text, int x, int y, int width, int height, int position, Color color, Color textColor, double visibilityState) {
+ //setVisibilityState(state);
+ double opacity = getOpacity(visibilityState);
+ double textOpacity = getTextOpacity(visibilityState);
if (text == null) {
text = "NULL";
}
diff --git a/src/main/java/ru/ifmo/acm/datapassing/BreakingNewsData.java b/src/main/java/ru/ifmo/acm/datapassing/BreakingNewsData.java
index 67cc0eea..b3f61329 100644
--- a/src/main/java/ru/ifmo/acm/datapassing/BreakingNewsData.java
+++ b/src/main/java/ru/ifmo/acm/datapassing/BreakingNewsData.java
@@ -11,6 +11,10 @@ public BreakingNewsData initialize() {
BreakingNewsData data = MainScreenData.getMainScreenData().breakingNewsData;
this.timestamp = data.timestamp;
this.isVisible = data.isVisible;
+ this.isLive = data.isLive;
+ this.teamId = data.teamId;
+ this.problemId = data.problemId;
+ this.infoType = data.infoType;
return this;
}
@@ -19,16 +23,17 @@ public void recache() {
}
public synchronized boolean setNewsVisible(boolean visible, String type, boolean isLive, String info) {
+ if (visible && isVisible) {
+ return false;
+ }
+
this.isVisible = visible;
if (visible) {
String[] zz = info.split(" ");
- int teamId = Integer.parseInt(zz[0]);
+ int teamId = Integer.parseInt(zz[0]) - 1;
int problemId = zz[1].charAt(0) - 'A';
- if (timestamp + MainScreenData.getProperties().sleepTime > System.currentTimeMillis() && isVisible) {
- return false;
- }
TeamInfo teamInfo = MainScreenData.getProperties().contestInfo.getParticipant(teamId);
this.teamId = teamId;
this.problemId = problemId;
@@ -47,7 +52,8 @@ public void update() {
synchronized (breakingNewsLock) {
//System.err.println(PCMSEventsLoader.getInstance().getContestData().getTeamsNumber());
if (System.currentTimeMillis() > timestamp +
- MainScreenData.getProperties().breakingNewsTimeToShow) {
+ MainScreenData.getProperties().breakingNewsTimeToShow +
+ MainScreenData.getProperties().sleepTime) {
isVisible = false;
change = true;
}
@@ -62,12 +68,14 @@ public String toString() {
public String getStatus() {
if (isVisible) {
- String status = "Breaking news (%s) are shown for team %d and problem %c for %d seconds";
+ String status = "Breaking news (%s) are shown for team %s and problem %c for %d seconds";
- long time = (timestamp + MainScreenData.getProperties().breakingNewsTimeToShow - System.currentTimeMillis()) / 1000;
- String type = isLive ? "Live" : infoType;
+ long time = (timestamp + MainScreenData.getProperties().breakingNewsTimeToShow
+ + MainScreenData.getProperties().sleepTime
+ - System.currentTimeMillis()) / 1000;
+ String type = isLive ? infoType : "record";
- return String.format(status, type, teamId, (char)('A' + problemId), time);
+ return String.format(status, type, teamName, (char) ('A' + problemId), time);
} else {
return "Breaking news aren't shown";
}
diff --git a/src/main/java/ru/ifmo/acm/datapassing/StandingsData.java b/src/main/java/ru/ifmo/acm/datapassing/StandingsData.java
index b17e1815..9eaac54c 100644
--- a/src/main/java/ru/ifmo/acm/datapassing/StandingsData.java
+++ b/src/main/java/ru/ifmo/acm/datapassing/StandingsData.java
@@ -4,6 +4,7 @@
import ru.ifmo.acm.backend.player.widgets.StandingsWidget;
import ru.ifmo.acm.events.EventsLoader;
import ru.ifmo.acm.mainscreen.MainScreenData;
+import ru.ifmo.acm.mainscreen.MainScreenProperties;
public class StandingsData implements CachedData {
@Override
@@ -31,10 +32,6 @@ public String toString() {
(isBig() ? " big standings are shown" : " compact standings are shown");
}
- public long getLatency() {
- return latency;
- }
-
public void recache() {
Data.cache.refresh(StandingsData.class);
}
@@ -53,8 +50,8 @@ public void setStandingsVisible(boolean visible, StandingsType type, boolean isB
public static long getTotalTime(boolean isBig, StandingsType type) {
return isBig ?
- BigStandingsWidget.totalTime(type, EventsLoader.getInstance().getContestData().getTeamsNumber()) + latency :
- StandingsWidget.totalTime(type, EventsLoader.getInstance().getContestData().getTeamsNumber()) + latency;
+ BigStandingsWidget.totalTime(type, EventsLoader.getInstance().getContestData().getTeamsNumber()) + MainScreenData.getProperties().latency :
+ StandingsWidget.totalTime(type, EventsLoader.getInstance().getContestData().getTeamsNumber()) + MainScreenData.getProperties().latency;
}
public void update() {
@@ -98,8 +95,6 @@ public void setBig(boolean big) {
public boolean isBig;
public OptimismLevel optimismLevel = OptimismLevel.NORMAL;
- public static long latency;
-
final private Object standingsLock = new Object();
public enum StandingsType {
diff --git a/src/main/java/ru/ifmo/acm/events/PCMS/PCMSRunInfo.java b/src/main/java/ru/ifmo/acm/events/PCMS/PCMSRunInfo.java
index 33407f71..9ba8d7cd 100644
--- a/src/main/java/ru/ifmo/acm/events/PCMS/PCMSRunInfo.java
+++ b/src/main/java/ru/ifmo/acm/events/PCMS/PCMSRunInfo.java
@@ -24,6 +24,10 @@ public class PCMSRunInfo implements RunInfo {
this.firstToSolve = firstToSolve;
}
+ public int getId() {
+ throw new AssertionError("PCMSRunInfo doesn't have id");
+ }
+
public boolean isAccepted() {
return "AC".equals(result);
}
diff --git a/src/main/java/ru/ifmo/acm/events/RunInfo.java b/src/main/java/ru/ifmo/acm/events/RunInfo.java
index 4ac91d29..16e47e7c 100644
--- a/src/main/java/ru/ifmo/acm/events/RunInfo.java
+++ b/src/main/java/ru/ifmo/acm/events/RunInfo.java
@@ -1,6 +1,7 @@
package ru.ifmo.acm.events;
public interface RunInfo {
+ int getId();
boolean isAccepted();
boolean isJudged();
String getResult();
diff --git a/src/main/java/ru/ifmo/acm/events/WF/WFEventsLoader.java b/src/main/java/ru/ifmo/acm/events/WF/WFEventsLoader.java
index 3354a9cf..15311925 100644
--- a/src/main/java/ru/ifmo/acm/events/WF/WFEventsLoader.java
+++ b/src/main/java/ru/ifmo/acm/events/WF/WFEventsLoader.java
@@ -77,7 +77,8 @@ private List problemsInfoRead() throws IOException {
problem.name = val;
break;
case "rgb":
- problem.color = Color.decode(val.substring(1, 8));
+ //System.err.println(val + " " + val.length());
+ problem.color = Color.decode(val);
break;
}
}
diff --git a/src/main/java/ru/ifmo/acm/mainscreen/MainScreenStandingsView.java b/src/main/java/ru/ifmo/acm/mainscreen/MainScreenStandingsView.java
index 0c088c36..8ba4e200 100644
--- a/src/main/java/ru/ifmo/acm/mainscreen/MainScreenStandingsView.java
+++ b/src/main/java/ru/ifmo/acm/mainscreen/MainScreenStandingsView.java
@@ -64,17 +64,20 @@ public Component getBreakingNewsController() {
isLive = new CheckBox("Is live");
isLive.addValueChangeListener(event -> {
- types.setValue(isLive.getValue() ? null: TeamWidget.types[0]);
- for (String type : TeamWidget.types) {
- types.setItemEnabled(type, isLive.isEmpty());
- }
+ //types.setValue(isLive.getValue() ? null: TeamWidget.types[0]);
+// for (String type : TeamWidget.types) {
+// types.setItemEnabled(type, !isLive.getValue());
+// }
+ types.setEnabled(isLive.getValue());
breakingNewsStatus.setValue(getBreakingNewsStatus());
});
+ isLive.setValue(false);
types = new OptionGroup();
types.addItems(TeamWidget.types);
types.addStyleName(ValoTheme.OPTIONGROUP_HORIZONTAL);
types.setValue(TeamWidget.types[0]);
+ types.setEnabled(false);
team = new TextField("Team: ");
team.setSizeFull();
@@ -85,7 +88,12 @@ public Component getBreakingNewsController() {
Notification.show("Team field requires team id and problem id");
} else {
if (!mainScreenData.breakingNewsData.setNewsVisible(true, (String) types.getValue(), isLive.getValue(), team.getValue())) {
- Notification.show("You need to wait 30 seconds first", Notification.Type.WARNING_MESSAGE);
+ Notification.show(
+ String.format("You need to wait while current breaking news is shown"),
+ Notification.Type.WARNING_MESSAGE
+ );
+ } else {
+ team.clear();
}
breakingNewsStatus.setValue(getBreakingNewsStatus());
}
diff --git a/src/main/resources/mainscreen.properties b/src/main/resources/mainscreen.properties
index a5b10a6e..7107ac6b 100644
--- a/src/main/resources/mainscreen.properties
+++ b/src/main/resources/mainscreen.properties
@@ -3,13 +3,14 @@ backup.advertisements=advertisements.txt
advertisement.time=5000
person.time=5000
latency.time=2000
-breakingnews.time=5000
+breakingnews.time=20000
data.update=1000
data.host=localhost
data.port=25675
info.types=screen;camera
info.screen=http://10.25.94.24:9080/video/screen/%d
info.camera=http://10.25.94.24:9080/video/camera/%d
+info.record=pics/logo.png
sleep.time=3000
camera.number=2
@@ -17,6 +18,6 @@ camera.url.1=null
camera.name.1=studio
camera.url.2=null
camera.name.2=commentators
-width=1920
-height=1080
+width=920
+height=560
rate=25
\ No newline at end of file