Skip to content

Commit 3a4602e

Browse files
authored
Merge pull request #2222 from hexlet-codebattle/add_new_game_types
Add new game types
2 parents e81f743 + e6828cd commit 3a4602e

File tree

86 files changed

+3341
-318
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+3341
-318
lines changed

services/app/apps/codebattle/assets/css/style.scss

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,14 @@ a {
687687
opacity: 0;
688688
}
689689

690+
.cb-opacity-05 {
691+
opacity: 0.05;
692+
}
693+
694+
.cb-opacity-10 {
695+
opacity: 0.10;
696+
}
697+
690698
.cb-opacity-25 {
691699
opacity: 0.25;
692700
}
@@ -2095,12 +2103,12 @@ a.cb-text:hover {
20952103
border-color: $cb-secondary-focus-border;
20962104
}
20972105

2098-
&:hover {
2106+
&:hover:not(:disabled):not(.disabled) {
20992107
background-color: $cb-secondary-hover-background;
21002108
border-color: $cb-secondary-hover-border;
21012109
}
21022110

2103-
&:focus {
2111+
&:focus:not(:disabled):not(.disabled) {
21042112
background-color: $cb-secondary;
21052113
border-color: $cb-secondary-focus-border;
21062114
}
@@ -2140,13 +2148,13 @@ a.cb-text:hover {
21402148
border-color: $cb-secondary-focus-border;
21412149
}
21422150

2143-
&:hover {
2151+
&:hover:not(:disabled):not(.disabled) {
21442152
color: white;
21452153
background-color: $cb-secondary-hover-background;
21462154
border-color: $cb-secondary-hover-border;
21472155
}
21482156

2149-
&:focus {
2157+
&:focus:not(:disabled):not(.disabled) {
21502158
color: white;
21512159
background-color: $cb-secondary;
21522160
border-color: $cb-secondary-focus-border;
@@ -2178,8 +2186,12 @@ a.cb-text:hover {
21782186
background-color: $cb-success;
21792187
border-color: $cb-success;
21802188

2181-
&:hover:not(:disabled),
2182-
&:hover:not(.disabled) {
2189+
&:hover:not(:disabled):not(.disabled) {
2190+
background-color: $cb-hovered-success;
2191+
border-color: $cb-hovered-success;
2192+
}
2193+
2194+
&:focus:not(:disabled):not(.disabled) {
21832195
background-color: $cb-hovered-success;
21842196
border-color: $cb-hovered-success;
21852197
}
@@ -2188,8 +2200,7 @@ a.cb-text:hover {
21882200
.cb-btn-outline-success {
21892201
border-color: $cb-success;
21902202

2191-
&:hover:not(:disabled),
2192-
&:hover:not(.disabled) {
2203+
&:hover:not(:disabled):not(.disabled) {
21932204
background-color: $cb-hovered-success;
21942205
border-color: $cb-hovered-success;
21952206
}

services/app/apps/codebattle/assets/js/__tests__/RootContainer.test.jsx

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,18 @@ import waitingRoom from '../widgets/machines/waitingRoom';
1919
import RootContainer from '../widgets/pages/RoomWidget';
2020
import reducers from '../widgets/slices';
2121

22+
jest.mock('pixelmatch', () => ({}));
23+
2224
jest.mock('monaco-editor', () => ({
2325
editor: {
24-
defineTheme: () => {},
26+
defineTheme: () => { },
2527
create: () => ({
26-
dispose: () => {},
27-
onDidChangeModelContent: () => {},
28-
setValue: () => {},
29-
getValue: () => {},
30-
getModel: () => {},
31-
focus: () => {},
28+
dispose: () => { },
29+
onDidChangeModelContent: () => { },
30+
setValue: () => { },
31+
getValue: () => { },
32+
getModel: () => { },
33+
focus: () => { },
3234
}),
3335
},
3436
}));
@@ -37,7 +39,7 @@ jest.mock('monaco-vim', () => ({
3739
VimMode: class {
3840
constructor() {
3941
return {
40-
dispose: () => {},
42+
dispose: () => { },
4143
};
4244
}
4345
},
@@ -242,38 +244,6 @@ test('test rendering preview game component', async () => {
242244
expect(await findByText(/Examples:/)).toBeInTheDocument();
243245
});
244246

245-
test('test game guide', async () => {
246-
const store = configureStore({
247-
reducer,
248-
preloadedState,
249-
});
250-
251-
const { findByRole, user } = setup(
252-
<Provider store={store}>
253-
<NiceModal.Provider>
254-
<RootContainer
255-
pageName="game"
256-
mainMachine={createMachine({ predictableActionArguments: true, ...game })}
257-
taskMachine={createMachine({ predictableActionArguments: true, ...task })}
258-
editorMachine={createMachine({ predictableActionArguments: true, ...editor })}
259-
waitingRoomMachine={createMachine({ predictableActionArguments: true, ...waitingRoom })}
260-
/>
261-
</NiceModal.Provider>
262-
</Provider>,
263-
);
264-
265-
const showGuideButton = await findByRole('button', { name: 'Show guide' });
266-
267-
await user.click(showGuideButton);
268-
269-
const closeGuideButton = await findByRole('button', { name: 'Close' });
270-
expect(closeGuideButton).toBeInTheDocument();
271-
272-
await user.click(closeGuideButton);
273-
274-
expect(closeGuideButton).not.toBeInTheDocument();
275-
});
276-
277247
test('test a bot invite button', async () => {
278248
const store = configureStore({
279249
reducer,

services/app/apps/codebattle/assets/js/__tests__/UserSettings.test.jsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,19 @@ describe('UserSettings test cases', () => {
7676
.spyOn(axios, 'patch')
7777
.mockResolvedValueOnce({ data: {} });
7878
const {
79-
getByRole, getByLabelText, getByTestId, user,
80-
} = setup(
81-
<Provider store={store}>
82-
<UserSettings />
83-
</Provider>,
79+
getByRole, getByLabelText, getByTestId, user,
80+
} = setup(
81+
<Provider store={store}>
82+
<UserSettings />
83+
</Provider>,
8484
);
8585
const submitButton = getByLabelText('SubmitForm');
8686
const nameInput = getByTestId('nameInput');
87-
const langSelect = getByTestId('langSelect');
87+
const codeLangSelect = getByTestId('code-langSelect');
8888

8989
await user.clear(nameInput);
9090
await user.type(nameInput, 'Dmitry');
91-
await user.selectOptions(langSelect, 'Javascript');
91+
await user.selectOptions(codeLangSelect, 'Javascript');
9292
await user.click(submitButton);
9393

9494
await waitFor(() => {
@@ -98,6 +98,10 @@ describe('UserSettings test cases', () => {
9898
clan: '',
9999
name: 'Dmitry',
100100
lang: 'js',
101+
locale: undefined,
102+
lang_view: 'code',
103+
db_type: '',
104+
style_lang: '',
101105
sound_settings: {
102106
level: 6,
103107
type: 'standard',
@@ -111,11 +115,11 @@ describe('UserSettings test cases', () => {
111115

112116
test('failed user settings update', async () => {
113117
const {
114-
getByTestId, getByLabelText, findByRole, findByText, user,
115-
} = setup(
116-
<Provider store={store}>
117-
<UserSettings />
118-
</Provider>,
118+
getByTestId, getByLabelText, findByRole, findByText, user,
119+
} = setup(
120+
<Provider store={store}>
121+
<UserSettings />
122+
</Provider>,
119123
);
120124
const submitButton = getByLabelText('SubmitForm');
121125
const nameInput = getByTestId('nameInput');
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
11
import dayjs from 'dayjs';
22
import duration from 'dayjs/plugin/duration';
33
import timezone from 'dayjs/plugin/timezone';
4+
import updateLocale from 'dayjs/plugin/updateLocale';
45
import utc from 'dayjs/plugin/utc';
56

67
dayjs.extend(utc);
78
dayjs.extend(timezone);
89
dayjs.extend(duration);
10+
dayjs.extend(updateLocale);
11+
12+
const locale = dayjs.locale();
13+
14+
// const locale = dayjs.locale('es');
15+
// dayjs.tz.setDefault('Europe/Madrid');
16+
console.log(`Local: ${dayjs.tz.guess()}`);
17+
/* eslint-disable-next-line */
18+
19+
dayjs.updateLocale(locale, {
20+
weekStart: 1,
21+
});
922

1023
export default dayjs;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { toPng } from 'html-to-image';
2+
3+
const messageType = 'cssbattle';
4+
5+
// if (event.origin.startsWith('https://codebattle.hexlet.io/games/')) {
6+
window.addEventListener(
7+
'message',
8+
event => {
9+
try {
10+
if (event.data.type !== 'cssbattle') {
11+
return;
12+
}
13+
14+
window.parent.postMessage(
15+
{ type: messageType, data: event.data },
16+
event.origin,
17+
);
18+
19+
if (event.data?.userId) {
20+
const { bodyStr, userId } = event.data;
21+
22+
document.body.innerHTML = bodyStr;
23+
24+
toPng(document.body).then(dataUrl => {
25+
window.parent.postMessage(
26+
{ type: messageType, dataUrl, userId },
27+
event.origin,
28+
);
29+
});
30+
}
31+
} catch (e) {
32+
console.error(e.message);
33+
}
34+
},
35+
false,
36+
);

services/app/apps/codebattle/assets/js/socket.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,14 @@ export const channelMethods = {
7676
gameScore: 'game:score',
7777
gameCancel: 'game:cancel',
7878
gameCreate: 'game:create',
79-
cssGameCreate: 'game:css:create',
79+
experimentGameCreate: 'game:experiment:create',
8080
gameCreateInvite: 'game:create_invite',
8181
gameAcceptInvite: 'game:accept_invite',
8282
gameDeclineInvite: 'game:decline_invite',
8383
gameCancelInvite: 'game:cancel_invite',
8484

8585
reportOnPlayer: 'game:report',
86+
gameTaskChangeTarget: 'game:task:change_target',
8687

8788
chatAddMsg: 'chat:add_msg',
8889
chatCommand: 'chat:command',

services/app/apps/codebattle/assets/js/widgets/components/Editor.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import PropTypes from 'prop-types';
66

77
import '../initEditor';
88
import languages from '../config/languages';
9+
import { actions } from '../slices';
910
import useEditor from '../utils/useEditor';
1011

1112
import EditorLoading from './EditorLoading';
@@ -105,6 +106,8 @@ Editor.propTypes = {
105106
editable: PropTypes.bool,
106107
roomMode: PropTypes.string.isRequired,
107108
checkResult: PropTypes.func.isRequired,
109+
toggleMuteSound: PropTypes.func,
110+
mute: PropTypes.bool,
108111
userType: PropTypes.string.isRequired,
109112
userId: PropTypes.number.isRequired,
110113
};
@@ -114,8 +117,10 @@ Editor.defaultProps = {
114117
lineNumbers: 'on',
115118
syntax: 'js',
116119
fontSize: 16,
120+
mute: true,
117121
editable: false,
118122
loading: false,
123+
toggleMuteSound: actions.toggleMuteSound,
119124
};
120125

121126
export default memo(Editor);
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import React, { memo } from 'react';
2+
3+
import cn from 'classnames';
4+
import { useSelector } from 'react-redux';
5+
6+
import { getPregressbarClass, getPregressbarWidth } from '@/pages/lobby/GameProgressBar';
7+
8+
import EditorThemeCodes from '../config/editorThemes';
9+
import * as selectors from '../selectors';
10+
11+
function EditorGameBar({ userId, theme }) {
12+
const checkResult = useSelector(selectors.executionOutputSelector(userId));
13+
14+
const panelClassName = cn('d-flex position-absolute justify-content-center w-100', {
15+
'bg-white': theme === EditorThemeCodes.light,
16+
'bg-dark': theme === EditorThemeCodes.dark,
17+
});
18+
const editorBar = cn(
19+
'cb-editor-game-progress-bar rounded-bottom bg-light border-top-0',
20+
'd-flex justify-content-center pb-2 pt-1 px-4',
21+
{
22+
'bg-light': theme === EditorThemeCodes.light,
23+
'bg-dark': theme === EditorThemeCodes.dark,
24+
},
25+
);
26+
27+
return (
28+
<div className={panelClassName} title={checkResult.status}>
29+
<div className={editorBar}>
30+
<div className={getPregressbarClass({ checkResult }, theme)}>
31+
<div
32+
className="cb-asserts-progress"
33+
style={{
34+
width: getPregressbarWidth({ checkResult, theme }),
35+
}}
36+
/>
37+
</div>
38+
</div>
39+
</div>
40+
);
41+
}
42+
43+
export default memo(EditorGameBar);

0 commit comments

Comments
 (0)