Skip to content

Commit

Permalink
Show currently online players to home page
Browse files Browse the repository at this point in the history
  • Loading branch information
tmalahie committed Jun 19, 2022
1 parent 1593bf1 commit 9e8ae1a
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 23 deletions.
1 change: 1 addition & 0 deletions v2/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"react": "17.0.2",
"react-cookie": "^4.1.1",
"react-dom": "17.0.2",
"react-tooltip": "^4.2.21",
"sass": "^1.43.5"
},
"devDependencies": {
Expand Down
137 changes: 126 additions & 11 deletions v2/app/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import Skeleton from '../components/Skeleton/Skeleton';
import useAuthUser from '../hooks/useAuthUser';
import useCreations from '../hooks/useCreations';
import { useTranslation } from 'next-i18next';
import ReactTooltip from 'react-tooltip';

const screenshots = [[{
xs: ss1xs,
Expand Down Expand Up @@ -148,6 +149,7 @@ const Home: NextPage = () => {
function dispRankTab(e, tab) {
e.preventDefault();
setLeaderboardTab(tab);
setDismissedRankTabs({ ...dismissedRankTabs, [tab]: true });
if (tab >= LeaderboardTab.TT_150)
setCurrentTtCc(tab);
}
Expand Down Expand Up @@ -474,6 +476,14 @@ const Home: NextPage = () => {
}
}, [leaderboardTab, vsLeaderboardFiltered, battleLeaderboardFiltered, tt150LeaderboardFiltered, tt200LeaderboardFiltered]);

const { data: activeLobbiesData } = useSmoothFetch<ActiveLobbiesData>("/api/getOnlinePlayers.php", {
placeholder: () => ({
vs: [],
battle: []
})
});
const [dismissedRankTabs, setDismissedRankTabs] = useState({});

return (
<ClassicPage className={styles.Home} page="home">
<Head>
Expand Down Expand Up @@ -871,25 +881,22 @@ const Home: NextPage = () => {
<div className={styles.ranking_tabs}>
<a className={cx({
[styles.tab_selected]: leaderboardTab === LeaderboardTab.VS
})} href="#null" onClick={(e) => dispRankTab(e, 0)}>
})} href="#null" onClick={(e) => dispRankTab(e, LeaderboardTab.VS)}>
{t("Vs_mode")}
{/* print_badge(0); */}
</a><a className={cx({
[styles.tab_selected]: leaderboardTab === LeaderboardTab.BATTLE
})} href="#null" onClick={(e) => dispRankTab(e, 1)}>
})} href="#null" onClick={(e) => dispRankTab(e, LeaderboardTab.BATTLE)}>
{t("Battle")}
{/* print_badge(1); */}
{(!!activeLobbiesData["battle"].length && !dismissedRankTabs[LeaderboardTab.BATTLE]) && <span className={styles.ranking_badge}><span>{activeLobbiesData["battle"].length}</span></span>}
</a><a className={cx({
[styles.tab_selected]: leaderboardTab >= LeaderboardTab.TT_150
})} href="#null" onClick={(e) => dispRankTab(e, currentTtCc)}>
{t("Time_trial")}
</a>
</div>
<div id={styles.currently_online}>
{/*
print_active_players(0,'vs');
print_active_players(1,'battle');
*/}
{leaderboardTab === LeaderboardTab.VS && <ActiveLobbies data={activeLobbiesData} mode="vs" />}
{leaderboardTab === LeaderboardTab.BATTLE && <ActiveLobbies data={activeLobbiesData} mode="battle" />}
</div>
{(leaderboardTab >= LeaderboardTab.TT_150) && <div id={styles.clm_cc}>
<a className={cx({ [styles.tab_selected]: leaderboardTab === LeaderboardTab.TT_150 })} href="#null" onClick={(e) => dispRankTab(e, 2)}>150cc</a>
Expand All @@ -912,7 +919,7 @@ const Home: NextPage = () => {
</tbody>
</table>
</Skeleton>
<a className={cx(styles.right_section_actions, commonStyles.action_button)} href={leaderboardLink}>{t("Display_all")}</a>
<Link href={leaderboardLink}><a className={cx(styles.right_section_actions, commonStyles.action_button)}>{t("Display_all")}</a></Link>
</div>
<div className={styles.pub_section}>
<Ad width={300} height={250} bannerId="4492555127" />
Expand Down Expand Up @@ -970,7 +977,6 @@ function BirthdaysList() {
name: string;
}>
}>(`/api/getBirthdays.php`);
const language = useLanguage();
const { t } = useTranslation(localesNs);

const membersList = useMemo(() => {
Expand Down Expand Up @@ -998,7 +1004,6 @@ function BirthdaysList() {
</div>
}
function PendingNews() {
const language = useLanguage();
const { t } = useTranslation(localesNs);
const { data: pendingNewsPayload } = useSmoothFetch<{ count: number }>("/api/news/find", {
requestOptions: postData({
Expand All @@ -1020,7 +1025,117 @@ function PendingNews() {
<Link href={"/news#pending-news"}>{plural(t("n_pending"), pendingNewsPayload.count)}</Link> {t("news")}
</p>
}
type ActiveLobbyForMode = {
href: string;
key?: number;
creation?: {
type: string;
id: number;
name: string;
};
rules?: Record<string, any>;
players: {
id: number;
name: string;
pts: number;
}[];
};
type ActiveLobbiesData = {
vs: ActiveLobbyForMode[];
battle: ActiveLobbyForMode[];
};

type OnlineGameMode = "vs" | "battle";

interface ActiveLobbiesProps {
data: ActiveLobbiesData;
mode: OnlineGameMode;
}
function ActiveLobbies({ data, mode }: ActiveLobbiesProps) {
const { t } = useTranslation(localesNs);

const activeLobbiesForMode = data[mode];
if (!activeLobbiesForMode.length) return <></>;

const firstLobby = activeLobbiesForMode[0];
return <div className={styles.ranking_current} id={styles[`ranking_current_${mode}`]}>
<ReactTooltip place="top" effect="solid" offset={{top:-6}} />
{
(activeLobbiesForMode.length < 2) && !firstLobby.creation && !firstLobby.key ?
<span className={styles.ranking_list}>
{t("Currently_online_")}{" "}
<ActivePlayers data={firstLobby} mode={mode} single />
</span> : <>
{t("Currently_online_")}
<ul className={styles.ranking_list_game}>
{activeLobbiesForMode.map((lobby, i) => {
return <li key={lobby.href}>
<ActivePlayers data={lobby} mode={mode} />
</li>
})}
</ul>
</>
}
</div>
}

interface ActivePlayersProps {
data: ActiveLobbyForMode;
mode: OnlineGameMode;
single?: boolean;
}
function ActivePlayers({ data, mode, single }: ActivePlayersProps) {
const { t } = useTranslation(localesNs);

const creationTrKey = useMemo(() => {
if (!data.creation) return;

if (mode === "battle") return "the_arena";

switch (data.creation.type) {
case "circuits":
case "mkcircuits":
return "the_circuit";
case "mkcups":
return "the_cup";
case "mkmcups":
return "the_multicup";
}
}, [data]);
const rulesTrKey = useMemo(() => {
if (data.creation) return;
const defaultVal = single ? undefined : t("Normal");
if (!data.rules) return defaultVal;

const modeNames = {
cc: '${value}cc',
mirror: t("Mirror"),
team: t("Team"),
friendly: t('Friendly')
};

let ruleNames = [];
for (const key in modeNames) {
if (data.rules[key]) {
ruleNames.push(modeNames[key].replace('${value}', data.rules[key]));
}
}
if (!ruleNames.length) return defaultVal;
return ruleNames.join("+");
}, [data]);

const title = data.players.map(player => `${player.name} (${player.pts} pts)`).join("\n");
return <><span className={styles.ranking_activeplayernb} data-tip={title}>
{ t("n_Members", { count: data.players.length }) }
</span>
{" "}
{creationTrKey && <>{t("in_the_creation", { the_creation: t(creationTrKey) })}
{" "}<strong>{ data.creation?.name ?? t("Untitled") }</strong>{" "}
</>}
{rulesTrKey && t("in_mode_x", { x: t(rulesTrKey)})}
<a className={cx(commonStyles.action_button, styles.action_button)} href={data.href}>{t("Join")}</a>
</>
}

export const getServerSideProps = withServerSideProps({ localesNs })

Expand Down
15 changes: 14 additions & 1 deletion v2/app/public/locales/en/home.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,18 @@
"and_": " and ",
"Its_the_birthday_of": "It's the birthday of",
"n_pending": "%n pending",
"news": "news"
"news": "news",
"Currently_online_": "Currently online:",
"n_Members_one": "{{count}} member",
"n_Members_other": "{{count}} members",
"in_the_creation": "in {{ the_creation }}",
"the_circuit": "the circuit",
"the_arena": "the arena",
"the_cup": "the cup",
"the_multicup": "the multicup",
"in_mode_x": "in mode {{ x }}",
"Mirror": "Mirror",
"Team": "Team",
"Friendly": "Friendly",
"Join": "Join"
}
15 changes: 14 additions & 1 deletion v2/app/public/locales/fr/home.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,18 @@
"and_": " et ",
"Its_the_birthday_of": "C'est l'anniversaire de",
"n_pending": "%n news",
"news": "en attente de validation"
"news": "en attente de validation",
"Currently_online_": "Actuellement en ligne :",
"n_Members_one": "{{count}} membre",
"n_Members_other": "{{count}} membres",
"in_the_creation": "sur {{ the_creation }}",
"the_circuit": "le circuit",
"the_arena": "l'arène",
"the_cup": "la coupe",
"the_multicup": "la multicoupe",
"in_mode_x": "en mode {{ x }}",
"Mirror": "miroir",
"Team": "équipe",
"Friendly": "amical",
"Join": "Rejoindre"
}
9 changes: 9 additions & 0 deletions v2/app/styles/Home.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,15 @@
padding: 2px 8px;
font-size: 0.75em;
}
.ranking_current .ranking_list_game strong {
max-width: 200px;
display: inline-block;
vertical-align: middle;
line-height: 1em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.ranking_activeplayernb {
font-weight: bold;
text-decoration: underline;
Expand Down
13 changes: 13 additions & 0 deletions v2/app/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2510,6 +2510,14 @@ [email protected]:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==

react-tooltip@^4.2.21:
version "4.2.21"
resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.2.21.tgz#840123ed86cf33d50ddde8ec8813b2960bfded7f"
integrity sha512-zSLprMymBDowknr0KVDiJ05IjZn9mQhhg4PRsqln0OZtURAJ1snt1xi5daZfagsh6vfsziZrc9pErPTDY1ACig==
dependencies:
prop-types "^15.7.2"
uuid "^7.0.3"

[email protected]:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
Expand Down Expand Up @@ -3039,6 +3047,11 @@ [email protected], util@^0.12.0:
safe-buffer "^5.1.2"
which-typed-array "^1.1.2"

uuid@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b"
integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==

v8-compile-cache@^2.0.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
Expand Down
13 changes: 7 additions & 6 deletions v2/php-api/endpoints/getOnlinePlayers.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
if ($activeCourse['active']) {
foreach ($activeCourse['players'] as &$activePlayer) {
$game = $activePlayer['game'];
$playerId = $activePlayer['id'];
$playerId = +$activePlayer['id'];
$activePlayers[$game][$playerId] = $activePlayer;
}
unset($activePlayer);
Expand Down Expand Up @@ -107,7 +107,7 @@ function get_creation_payload(&$params) {
if (!$getNom) return null;
return array(
'type' => $table,
'id' => $params['cup'],
'id' => +$params['cup'],
'name' => $getNom['nom']
);
}
Expand All @@ -121,9 +121,9 @@ function get_players_payload($players) {
$res = array();
foreach ($players as $player) {
$res[] = array(
'id' => $player['id'],
'id' => +$player['id'],
'name' => $player['nom'],
'pts' => $player['pts']
'pts' => +$player['pts']
);
}
return $res;
Expand Down Expand Up @@ -154,12 +154,13 @@ function game_pk_sort($k1,$k2) {
$res[$game] = array();
foreach ($linkWithPlayers as $ph => $players) {
$firstPlayer = $players[0];
$res[$game][] = array(
$res[$game][] = compactObject(array(
'href' => get_creation_link($firstPlayer),
'key' => $firstPlayer['link'] ? +$firstPlayer['link'] : null,
'creation' => get_creation_payload($firstPlayer),
'rules' => get_rules_payload($firstPlayer),
'players' => get_players_payload($players)
);
));
}
}

Expand Down
15 changes: 11 additions & 4 deletions v2/php-api/includes/api.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
<?php
function getJsonBody() {
return json_decode(file_get_contents('php://input'));
return json_decode(file_get_contents('php://input'));
}
function renderResponse($response, $code = 200) {
http_response_code($code);
header('Content-Type: application/json');
echo json_encode($response);
http_response_code($code);
header('Content-Type: application/json');
echo json_encode($response);
}
function compactObject($arr) {
foreach ($arr as $key => $value) {
if ($value === null)
unset($arr[$key]);
}
return $arr;
}

0 comments on commit 9e8ae1a

Please sign in to comment.