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

Release beta v2 0.3 #802

Merged
merged 57 commits into from
Jul 8, 2022
Merged

Conversation

adamlerer
Copy link
Contributor

@adamlerer adamlerer commented Jul 1, 2022

Release v0.3 of the new beta UI.

IMPORTANT notes:

  1. Unlike previous beta versions, this one makes db modifications, meaning we will have to upgrade to 1.70. master is still on 1.68 though, so what do we do? We can either upgrade to 1.70 in prod, or switch the 1.69 and 1.70 changes and switch to 1.69 ...
  2. Should this be merged into master or staging?

Feature list:

  • turn off "Early Access" guard for Beta UI
  • allow games to specify a shorter phase length for R/B phases and grace periods, vs M phases
  • Fix handling of civil disorders, pre-game phase, and vote processing in beta UI
  • Add blinking for unsaved unit orders
  • Add support for beta UI within the webdiplomacy docker configuration
  • fix longstanding bug in old UI in rulebook press, where moderator would broadcast a private message to everyone if they sent a message in a R/B phase

adamlerer and others added 30 commits June 14, 2022 10:38
Add phase names between messages
Don't broadcast a private message to everyone just because you are mod
* html sanitize fix

* fix lint errors

Co-authored-by: utiq <cesargutierrez@fb.com>
Don't give an exception if vote response is empty string (ie no votes)
WDIP-32: Turn off early access guard for beta
WDIP-21: Fix handling of Civil Disorder in beta UI
* docker-compose configuration

* put back temp change

* put back proxy in package.json

* port back to 8895

* Revert "port back to 8895"

This reverts commit a793f6a.

* Revert "put back proxy in package.json"

This reverts commit 091637c.

* add scripts to run development env out of the box

* fix entrypoint

* fix entrypoint

* fix permissions

* add config copy

* update variable

* update default values

Co-authored-by: utiq <cesargutierrez@fb.com>
WDIP-17: Different phase duration for retreats/builds/missed turns
…macy"

This reverts commit 327f288, reversing
changes made to f43b00e.
@adamlerer
Copy link
Contributor Author

@kestasjk I tried resolving the merge conflicts here, but at least on my private instance, I found that the current master branch isn't working properly (gamemaster doesn't start bot games, cancel doesn't work, etc.) so I was wondering if your changes from a few hours ago might have broken something.

Are changes on master auto-synced to webdiplomacy.net ? Because things are working fine there.

@kestasjk
Copy link
Owner

kestasjk commented Jul 3, 2022

Hi Adam,
Hmm that's odd..

I changed how votes are handled since it wasn't working reliably; PHP logic detected when a vote passed, and the logic was at a point where I didn't understand the intent. Also because it was in PHP you couldn't search for votes that need processing, you had to detect it when the vote is submitted or game is viewed by a player and then set a flag in memcache for the gamemaster to handle.
I replaced it with a query to search for votes to process that ignores votes from bots entirely. This is a change to the previous logic which did factor in votes from bots, but I couldn't make sense of what it was trying to do where it would sort of allow votes depending on whether the bot had gained or lots supply centers in the last 2-4 turns, so I figured (since it wasn't working for many anyway) I would simplify it right down and see if any issues arose.

Possibly unrelated but FYI: We were also still getting deadlocks / lock timeouts appear in the error logs that I wanted to resolve. When looking into the API I realized it was locking games for update, the most strict and intrusive lock type, to do read-only operations including just checking whether a user was in a game. With hindsight I'm impressed (with the hardware) that the site never became totally inoperable.
Part of the reason is knowing the new board does do a lot of background server requests, and I want to add an instant-play feature so anyone can go to a URL, no account needed, start a bot game and leave when they like, which might increase server load.

Yep webdiplomacy.net syncs with the master branch automatically, and it is in sync at the moment. Is it 1 human games that aren't processing or multi-human games, and are full human games processing? I didn't change how the gamemaster does game processing and it is working so I'm not sure what's going on there. I can see you've got some changes talking about database changes / vote processing etc so maybe there's a merge conflict of some sort. I want to try and finish up a couple of features today but I might be able to look at this merge. I do also want to get staging up to pace with the master branch so you can merge with staging again.

I'll try and bring the database/code version up to 1.71 today, and do a test of a clean install in docker, so you can merge in the database changes neatly into 1.72 via a install/1.71-1.72/update.sql script.

@adamlerer
Copy link
Contributor Author

adamlerer commented Jul 3, 2022

Thanks @kestasjk . Yeah, the vote logic was hard for me to understand as well, I sort of treated it as a black box. Once you update the code I'll probably start from scratch on how to initiate vote processing from the setVote API call (let me know if you have a suggestion).

Re locking: I didn't write this code, not surprised that this happened because the getAssociatedGame function was originally written for a limited purpose and got cargo-culted around for various purposes. Lucky it didn't cause any problems.

What's not working on my end is the processing (starting) of all-bot games. I haven't experimented with anything else.

I'll take another pass once you make your changes.

Copy link
Contributor

@TimothyJones TimothyJones left a comment

Choose a reason for hiding this comment

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

Hi there! I partially reviewed the react code. Nothing show stopping, but I left a number of optional comments about style improvements and risk reduction. If this is useful, I'm happy to review the rest of it.

@@ -101,6 +103,14 @@ const WDMainController: React.FC = function ({ children }): React.ReactElement {
// *not* yet seen (i.e. presumably they saw this phase when they were entering
// orders for it, before that phase ended and other powers' orders appeared).
dispatch(gameApiSliceActions.setViewedPhaseToLatestPhaseViewed());
if (status.status === "Left") {
Copy link
Contributor

Choose a reason for hiding this comment

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

Unrelated to this change, but I think it's better to declare the function outside the JSX inside a useCallback, otherwise there may be rendering overhead. In the current form, a new clickhandler function is created every time this component renders.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, although I believe this component renders rarely (only on phase updae).

noPhase || (displayedPhaseKey && overviewKey !== displayedPhaseKey);
noPhase ||
status.status === "Left" ||
(displayedPhaseKey && overviewKey !== displayedPhaseKey);
if (displayedPhaseKey === null && overview.phase) {
setDisplayedPhaseKey(overviewKey);
Copy link
Contributor

Choose a reason for hiding this comment

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

I might be missing something with this Controller pattern, but I believe this call (and the other dispatch calls) have side effects, which means they would properly be placed inside a useEffect or an event handler. I don't think it's right to call them directly in the render function.

Personally, I would put this whole check inside a selector - if you can compute it from the main state, you don't need to store it in separate state. Storing things you can compute is risky because you might forget to update them, or you might get out of sync with the main state in other ways.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lightvector wrote this code, but I believe the reason that this is stateful is that on a phase change, we want to remember the last phase that was being viewed, and let the user manually scroll forward to the current phase. Therefore, it's not a stateless function of the current state.

unitWidth,
unitHeight,
}): React.ReactElement {
const iconWidth =
type === "Fleet" ? FLEET_RAW_ICON_WIDTH : ARMY_RAW_ICON_WIDTH;
unit.unit.type === "Fleet" ? FLEET_RAW_ICON_WIDTH : ARMY_RAW_ICON_WIDTH;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a way to write this without needing to access it with unit.unit? I feel like there are two different meanings of unit here, and it's not obvious what the difference is during a skim read.

As an aside, knowing how to calculate the width and height doesn't feel like the responsibility of a controller - it might read better as a function that returns { iconWidth, iconHeight }

{type === "Fleet" && (
<WDFleetIcon iconState={iconState} country={meta.country} />
{unit.unit.type === "Fleet" && (
<WDFleetIcon iconState={unitState} country={unit.country} />
Copy link
Contributor

Choose a reason for hiding this comment

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

I like this unitState rename. Good catch.

@@ -14,6 +14,7 @@ import ArrowColor from "../../../enums/ArrowColor";
import drawArrowFunctional, {
getTargetXYWH,
getArrowX1Y1X2Y2,
makeSVGDrawAsUnsavedAnimateElement,
Copy link
Contributor

Choose a reason for hiding this comment

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

This name doesn't feel like it's as clear as it could be. Can it be more about what it is for, not how it does it?

@@ -14,13 +14,22 @@ import {
import WDCountdownPill from "./WDCountdownPill";
import WDPillScroller from "./WDPillScroller";

const getCurPhaseMinutes = function (phaseMinutes, phaseMinutesRB, phase) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as earlier about get - I think these are selectors or renderers, and would be better without the get prefix.

multiline
maxRows={4}
onChange={(text) => setUserMsg(text.target.value)}
onChange={(text) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment about not declaring these inline

@@ -128,6 +128,7 @@ export const setVoteStatus = createAsyncThunk(
vote: string;
voteOn: string;
}) => {
console.log("Submitting vote");
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this is meant to be in the PR (and probably should be a lint error)

@@ -143,14 +144,25 @@ export const markMessagesSeen = createAsyncThunk(
gameID: string;
seenCountryID: string;
}) => {
const { data } = await getGameApiRequest(
const { data } = await postGameApiRequest(
ApiRoute.MESSAGES_SEEN,
queryParams,
);
return data as string;
Copy link
Contributor

Choose a reason for hiding this comment

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

This as would be better put inside the *GameApiRequest functions, I think.

Also, since it's just a string that we're looking for, we could check that it's actually a string and throw an error if it isn't, too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know why this as string is here - the linter isn't complaining even when I remove it.

ApiRoute.MESSAGES_SEEN,
queryParams,
);
return data as string;
},
);

export const setBackFromLeft = createAsyncThunk(
Copy link
Contributor

Choose a reason for hiding this comment

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

I personally would not name these set as they can be confused with state setters. For consistency with the other function you could call it markBackFromLeft.

I like update for a prefix for server updates, and fetch for server gets.

In this case I would name the function markReturnedToGame

Also, probably it should be a put not a post, because (unless I'm missing something) this particular request is idempotent.

@kestasjk
Copy link
Owner

kestasjk commented Jul 3, 2022

Righto didn't get the anonymous game suspicion stuff done, but I've wrapped everything up and started a new release 1.70, and I've tested out a fresh install from the docker composer to check that it's all working. Next dev cycle probably won't be for a few weeks so that should let you make your changes without any moving parts.

@adamlerer
Copy link
Contributor Author

adamlerer commented Jul 5, 2022

Okay, I've merged in the latest master, things seem to be working correctly now.

@kestasjk there are still a couple things that aren't working quite properly for me right now:

  1. The UI behaves weirdly when you cancel a game, in either the old or new UI. To repro: create a bot game, then press cancel, in either UI. (The cancellation works, but the UI misbehaves because the game has disappeared).
  2. When I run docker-compose up, memcached doesn't work. The reason is that the memcached server is exposed as memcached:11211, while the PHP code looks for 127.0.0.1:11211. Solutions I've found are either to change the PHP code to $MC->addServer("memcached", 11211); or docker exec into the PHP machine and set up memcached there.

@TimothyJones I addressed some of your comments, but some of them would be better suited to a follow-up PR. It would certainly be great if you had time to improve the beta code systematically, there's definitely a lot of things that could be cleaned up and made more idiomatic. But I don't think fixing them locally in just a single place is worth it, and I don't want to do too much more in this PR since it's already quite large.

@kestasjk kestasjk merged commit 733311c into kestasjk:master Jul 8, 2022
@adamlerer adamlerer mentioned this pull request Jul 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants