Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added astronomical clock #144

Merged
merged 4 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/backend-api/src/main/kotlin/org/icpclive/api/Settings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,13 @@ data class ImageTickerSettings(
override fun toMessage() = ImageTickerMessage(this)
}


@Serializable
@SerialName("clock")
data class ClockTickerSettings(override val part: TickerPart, override val periodMs: Long) : TickerMessageSettings() {
data class ClockTickerSettings(
override val part: TickerPart,
override val periodMs: Long,
val timeZone: String? = null
) : TickerMessageSettings() {
override fun toMessage() = ClockTickerMessage(this)
}

Expand Down
2 changes: 0 additions & 2 deletions src/backend-api/src/main/kotlin/org/icpclive/api/Ticker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ class ImageTickerMessage(val settings: ImageTickerSettings)
}
}



@Serializable
@SerialName("clock")
class ClockTickerMessage(val settings: ClockTickerSettings) :
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/admin/src/components/TickerMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const addPresetButtons = [
{
type: "clock",
component: ClockIcon,
settings: { periodMs: 30000 },
settings: { periodMs: 30000, timeZone: "" },
}, {
part: "long",
type: "scoreboard",
Expand Down
20 changes: 20 additions & 0 deletions src/frontend/admin/src/components/TickerTableRow.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState } from "react";
import { DateTime } from "luxon";
import { TableCell, TableRow, TextField } from "@mui/material";
import Box from "@mui/material/Box";
import IconButton from "@mui/material/IconButton";
Expand All @@ -16,6 +17,7 @@ import { onChangeFieldEventHandler } from "./PresetsTableRow";

export function TickerTableRow({ data, onShow, onEdit, onDelete }) {
const [editData, setEditData] = useState();
const [errorMessage, setErrorMessage] = useState("");

const onClickEdit = () => {
if (editData === undefined) {
Expand All @@ -41,6 +43,24 @@ export function TickerTableRow({ data, onShow, onEdit, onDelete }) {
{data.settings.type === "image" && <ImageIcon/>}
</TableCell>
<TableCell component="th" scope="row">
{data.settings.type === "clock" &&
(editData === undefined ? data.settings.timeZone : (
<Box onSubmit={onSubmitEdit} component="form" type="submit">
<TextField autoFocus hiddenLabel fullWidth defaultValue={data.settings.timeZone}
id="filled-hidden-label-small" type="text" size="small" sx={{ width: 1 }}
error={errorMessage !== ""}
helperText={errorMessage}
onChange={(event) => {
const dateTime = DateTime.now().setZone(event.target.value);
if (dateTime.isValid || event.target.value === "") {
setErrorMessage("");
onChangeFieldEventHandler(setEditData, "timeZone")(event);
} else {
setErrorMessage(dateTime.invalidReason);
}
}}/>
</Box>)
)}
{data.settings.type === "text" &&
(editData === undefined ? data.settings.text : (
<Box onSubmit={onSubmitEdit} component="form" type="submit">
Expand Down
1 change: 1 addition & 0 deletions src/frontend/common/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,7 @@ export enum TickerPart {
export interface clock {
part: TickerPart;
periodMs: number;
timeZone?: string | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now there is a strange type in the typescript.
But I guess we will fix it once we (cc @kunyavskiy) figure out a way to canonize them to all be either null or undefined.

}

export interface image {
Expand Down
10 changes: 9 additions & 1 deletion src/frontend/overlay/src/components/molecules/Clock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const ContestClock = ({
globalTimeMode = false,
contestCountdownMode = false,
quietMode = false,
timeZone = null
}) => {
const formatTime = (time, fullFormat = false) => {
if (!fullFormat && quietMode && time > 5 * 60 * 1000) {
Expand All @@ -31,9 +32,16 @@ export const ContestClock = ({
}
}, [contestInfo, contestCountdownMode]);

const getDateTimeNowWithCustomTimeZone = (zone) =>
DateTime.now().setZone(zone).toFormat(quietMode ? "HH:mm" : "HH:mm:ss");

const getStatus = useCallback(() => {
if (globalTimeMode === true) {
return DateTime.now().setZone(new SystemZone()).toFormat(quietMode ? "HH:mm" : "HH:mm:ss");
return getDateTimeNowWithCustomTimeZone(timeZone ?? new SystemZone());
}

if (timeZone !== null) {
return getDateTimeNowWithCustomTimeZone(timeZone);
}

if (contestInfo === undefined) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import React from "react";
import { TextWrap } from "./Text";
import ContestClock from "../../molecules/Clock";

export const Clock = ({ part }) => {
export const Clock = ({ tickerSettings, part }) => {
return <TextWrap part={part}>
<ContestClock/>
<ContestClock
timeZone={tickerSettings.timeZone === "" ? null : tickerSettings.timeZone}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just make the default null or undefined instead of an empty string?

Copy link
Contributor Author

@Mond1c Mond1c Feb 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But if we have such a situation: we set "timeZone" to utc. Then we set "timeZone" to an empty string. In tickerSettings "timeZone" is now equals to an empty string. So it's not null => we have InvalidDateAndTime. But we expected contest time.

We can change this part of code:

const dateTime = DateTime.now().setZone(event.target.value);
if (dateTime.isValid || event.target.value === "") {
    setErrorMessage("");
    onChangeFieldEventHandler(setEditData, "timeZone")(event);
} else {
    setErrorMessage(dateTime.invalidReason);
}

But I don't think this is a good idea, becase we need to create a new function instead of using onChangeFieldEventHandler. (This necessary for this because if event.target.value is an empty string we can change value to null).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm talking mostly about backend behaviour here. As far as i can see this line of code just changes an empty string from the backend to a null

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I can do something like this:

override fun toMessage(): ClockTickerMessage {
    if (timeZone != null && timeZone.isEmpty()) {
        return ClockTickerMessage(ClockTickerSettings(part, periodMs, null))
    }
    return ClockTickerMessage(this)
} 

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

/>
</TextWrap>;
};

Expand Down
Loading