Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
20 changes: 20 additions & 0 deletions packages/back-nest/src/seeder/commands/challenge.seeder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,26 @@ export class ProjectSeedRunner extends CommandRunner {
'}';
thirdChallenge.project = project;

const fourthChallenge = new Challenge();
challenges.push(fourthChallenge);
fourthChallenge.id = '6be1759b-a6ed-445e-aeef-dad6d7083e45';
fourthChallenge.sha = '097f875bcfe0dd3703f5b3fd6837cc0bdbc2ccb8';
fourthChallenge.treeSha = 'ac219cef2ad7999fc95c8fd4eb3b945ba37abd43';
fourthChallenge.path = 'zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/SnapshotInfo.java';
fourthChallenge.language = 'java';
fourthChallenge.url =
'https://github.com/apache/zookeeper/blob/ac219cef2ad7999fc95c8fd4eb3b945ba37abd43/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/SnapshotInfo.java/#L25-L35';
fourthChallenge.content =
'public class SnapshotInfo {\n' +
'\tpublic long zxid;\n' +
'\tpublic long timestamp;\n' +
'\tSnapshotInfo(long zxid, long timestamp) {\n' +
'\t\tthis.zxid = zxid;\n' +
'\t\tthis.timestamp = timestamp;\n' +
'\t}\n' +
'}';
fourthChallenge.project = project;

return challenges;
}
}
11 changes: 9 additions & 2 deletions packages/webapp-next/modules/play2/components/RaceSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@ import { LanguageSelector } from "./race-settings/LanguageSelector";

export const RaceSettings: React.FC = () => {
const isOpen = useSettingsStore((s) => s.languageModalIsOpen);
const languageSelected = useSettingsStore((s) => s.languageSelected);
const language = languageSelected ? languageSelected.name : "language";
const languagesSelected = useSettingsStore((s) => s.languageSelected);
let language = "language";
if (languagesSelected.length > 0) {
if (languagesSelected.length === 1) {
language = languagesSelected[0].name;
} else {
language = `${languagesSelected.length} selected`;
}
}

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { getExperimentalServerUrl } from "../../../../common/utils/getServerUrl"
import { useSettingsStore, LanguageDTO, setLanguage } from "../../state/settings-store";
import { useGameStore } from "../../state/game-store";

const selectProgrammingLanguage = (languageSelected: LanguageDTO | null) => {
setLanguage(languageSelected);
if (languageSelected) {
const selectProgrammingLanguages = (languagesSelected: LanguageDTO[]) => {
setLanguage(languagesSelected);
if (languagesSelected.length > 0) {
useGameStore.getState().game?.next();
}
};
Expand All @@ -19,16 +19,27 @@ export function LanguageSelector() {
fetch(...args).then((res) => res.json())
);
const languages = data as undefined | { language: string; name: string }[];
const selectedLanguage = useSettingsStore((s) => s.languageSelected);
const selectedLanguages = useSettingsStore((s) => s.languageSelected);

const isSelected = (language: LanguageDTO) => {
return selectedLanguages.some((l) => l.language === language.language);
};

const displayValue = () => {
if (selectedLanguages.length === 0) return "nothing selected";
if (selectedLanguages.length === 1) return selectedLanguages[0].name;
return `${selectedLanguages.length} selected`;
}

return (
<div className="w-full text-dark-ocean font-thin w-[250px]">
<h2 className="text-xs mb-1 font-semibold uppercase tracking-widest">
select language
</h2>
<Listbox value={selectedLanguage} onChange={selectProgrammingLanguage}>
<Listbox value={selectedLanguages} onChange={selectProgrammingLanguages} multiple>
<div className="flex items-center">
<Listbox.Button className="flex items-center justify-between px-2 bg-gray-200 p-1 w-full rounded">
{selectedLanguage?.name || "nothing selected"}
{displayValue()}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
Expand All @@ -43,9 +54,9 @@ export function LanguageSelector() {
></path>
</svg>
</Listbox.Button>
{selectedLanguage && (
{selectedLanguages.length > 0 && (
<button
onClick={() => selectProgrammingLanguage(null)}
onClick={() => selectProgrammingLanguages([])}
className="flex items-center p-1 h-full bg-gray-200 ml-2 rounded"
>
<div className="w-2 text-red-500 fill-current mx-1">
Expand All @@ -59,7 +70,8 @@ export function LanguageSelector() {
<Listbox.Options static>
{languages?.map((language) => (
<Listbox.Option key={language.name} value={language}>
{({ active, selected }) => {
{({ active }) => {
const selected = isSelected(language);
return (
<li
className={`pl-2 flex items-center gap-2 my-1 p-1 rounded cursor-pointer ${
Expand Down
10 changes: 8 additions & 2 deletions packages/webapp-next/modules/play2/services/Game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ export class Game {
const connectedToValidRace =
useConnectionStore.getState().raceExistsInServer;
if (connectedToValidRace) {
const language = useSettingsStore.getState().languageSelected?.language;
const languages = useSettingsStore.getState().languageSelected;
const language = languages.length > 0
? languages[Math.floor(Math.random() * languages.length)].language
: undefined;
const dto = { language };
this.socket.emit("refresh_challenge", dto);
} else {
Expand All @@ -79,7 +82,10 @@ export class Game {

play() {
const isPublic = useSettingsStore.getState().defaultIsPublic;
const language = useSettingsStore.getState().languageSelected?.language;
const languages = useSettingsStore.getState().languageSelected;
const language = languages.length > 0
? languages[Math.floor(Math.random() * languages.length)].language
: undefined;
const dto = { language, isPublic };
this.socket.emit("play", dto);
}
Expand Down
29 changes: 17 additions & 12 deletions packages/webapp-next/modules/play2/state/settings-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface SettingsState {
profileModalIsOpen: boolean;
projectModalIsOpen: boolean;
publicRacesModalIsOpen: boolean;
languageSelected: LanguageDTO | null;
languageSelected: LanguageDTO[];
smoothCaret: boolean;
syntaxHighlighting: boolean;
raceIsPublic: boolean;
Expand Down Expand Up @@ -43,19 +43,24 @@ function getInitialToggleStateFromLocalStorage(
return defaultToggleValue;
}

function getInitialLanguageFromLocalStorage(key: string): LanguageDTO | null {
function getInitialLanguageFromLocalStorage(key: string): LanguageDTO[] {
if (typeof document !== "undefined" && window) {
let languageStr = localStorage.getItem(key) ?? "";
let lang;
try {
lang = JSON.parse(languageStr);
} catch (e) {}
if (!lang?.language || !lang?.name) {
return null;
} catch (e) { }

// this is to migrate from the old single language format
if (lang && !Array.isArray(lang) && lang.language && lang.name) {
return [lang];
}

if (Array.isArray(lang)) {
return lang;
}
return lang;
}
return null;
return [];
}

export const useSettingsStore = create<SettingsState>((_set, _get) => ({
Expand Down Expand Up @@ -84,15 +89,15 @@ export const setCaretType = (caretType: "smooth" | "block") => {
useSettingsStore.setState((state) => ({ ...state, smoothCaret }));
};

export const setLanguage = (language: LanguageDTO | null) => {
let stored = "";
if (language) {
stored = JSON.stringify(language);
export const setLanguage = (languages: LanguageDTO[]) => {
let stored = "[]";
if (languages) {
stored = JSON.stringify(languages);
}
localStorage.setItem(LANGUAGE_KEY, stored);
useSettingsStore.setState((state) => ({
...state,
languageSelected: language,
languageSelected: languages,
}));
};

Expand Down