Commit d8ec8044 authored by Ayush's avatar Ayush

Add compile components

parent 2ce9ffeb
......@@ -18,6 +18,7 @@ const routes: Routes = [
{path: 'files', component: FileComponent, canActivate: [AuthGuard]},
{path: 'login', component: LoginComponent},
{path: 'register', component: RegisterComponent},
{path: 'arena', redirectTo: '/arena/file/new'},
{path: '**', redirectTo: '/home'},
];
......
......@@ -9,10 +9,10 @@ import {HeaderComponent} from './header/header.component';
import {ApiService} from './api.service';
import {IdeCompileComponent} from './ide-compile/ide-compile.component';
import {InputComponent} from './input/input.component';
import {TestcaseStatusComponent} from './testcase-status/testcase-status.component';
import {SaveFileComponent} from './save-file/save-file.component';
import {FileComponent} from './file/file.component';
import {FileService} from './file.service';
import { SubmitTryCodeComponent } from './submit-try-code/submit-try-code.component';
@NgModule({
declarations: [
......@@ -21,9 +21,9 @@ import {FileService} from './file.service';
routerComponents,
IdeCompileComponent,
InputComponent,
TestcaseStatusComponent,
SaveFileComponent,
FileComponent
FileComponent,
SubmitTryCodeComponent
],
imports: [
BrowserModule,
......
......@@ -3,11 +3,12 @@
</div>
<div id="toggle-lang">C++</div>
<div id="attempt">
<button id="input">Custom Input</button>
<button id="try">Try Code</button>
<button id="submit">Submit Code</button>
<button id="input" (click)="inputField.setState(true)">Custom Input</button>
<button id="try" (click)="tryCode(0)" [class.disabled]="compilationError">{{compilationError ? 'Error' : 'Try Code'}}</button>
<button id="submit" (click)="tryCode(1)" [class.disabled]="compilationError">{{compilationError ? 'Encountered' : 'Submit Code'}}</button>
</div>
<label for="editor"></label>
<textarea id="editor" name="editor"></textarea>
</div>
<app-input></app-input>
<app-input (valueEmit)="customInput = $event"></app-input>
<app-submit-try-code [problem]="problem"></app-submit-try-code>
......@@ -44,6 +44,17 @@
background: var(--color);
color: var(--bgcolor);
}
&:hover {
background: var(--color);
color: var(--bgcolor);
}
&.disabled:hover {
cursor: default;
background: transparent;
color: #ddf;
}
}
}
}
......@@ -56,6 +67,10 @@ label {
.container {
padding: 20px 0;
}
#attempt, #toggle-lang {
right: 4px !important;
}
}
@media screen and (max-width: 900px) {
......
import {Component, OnInit} from '@angular/core';
import {Component, OnInit, ViewChild} from '@angular/core';
import {Router} from '@angular/router';
import {Problem} from '../problem';
import {ProblemService} from '../problem.service';
import {File} from '../file';
import {ApiService} from '../api.service';
import {InputComponent} from '../input/input.component';
import {SubmitTryCodeComponent} from '../submit-try-code/submit-try-code.component';
import {RunCodeService} from '../run-code.service';
declare const CodeMirror: any;
......@@ -16,9 +18,14 @@ export class ArenaComponent implements OnInit {
id: number;
problem: Problem;
files: File[] = [];
customInput = '';
compilationError = false;
constructor(public router: Router, private problemService: ProblemService, private apiService: ApiService) {
@ViewChild(InputComponent) inputField: InputComponent;
@ViewChild(SubmitTryCodeComponent) submitField: SubmitTryCodeComponent;
constructor(public router: Router, private problemService: ProblemService, private apiService: ApiService,
private runCodeService: RunCodeService) {
}
ngOnInit(): void {
......@@ -33,7 +40,7 @@ export class ArenaComponent implements OnInit {
matchBrackets: true
});
editor.setSize('auto', '70vh');
editor.setValue(this.problem.default_code[0]);
editor.setValue(this.problem.code[0]);
Object.assign((document.getElementsByClassName('CodeMirror')[0] as HTMLTextAreaElement).style, {
borderBottom: '1px solid #ddf',
padding: '20px',
......@@ -51,21 +58,13 @@ export class ArenaComponent implements OnInit {
const th = this as HTMLDivElement;
activeLang = (activeLang + 1) % 3;
th.innerHTML = langs[activeLang];
editor.setValue(problem.default_code[activeLang]);
editor.setValue(problem.code[activeLang]);
editor.setOption('mode', langsMime[activeLang]);
};
const filename = this.id.toString(10);
const username = JSON.parse(this.apiService.getToken()).username;
for (const ext of extensions) {
this.files.push({
username,
filename,
language: ext,
text: '',
path: '/'
});
}
editor.on('update', () => {
this.problem.code[activeLang] = editor.getValue();
});
}
......@@ -76,4 +75,19 @@ export class ArenaComponent implements OnInit {
});
}
tryCode(c): void {
this.runCodeService.compileProblemFile(this.problem)
.subscribe(data => {
if (document.getElementById('try').classList.contains('disabled')) {return; }
this.submitField.submitting = c;
this.submitField.reset();
this.submitField.isActive = true;
}, error => {
this.compilationError = true;
setTimeout(() => {
this.compilationError = false;
}, 3000);
});
}
}
......@@ -2,7 +2,7 @@
<a *ngIf="!loggedIn" routerLink="/register" routerLinkActive="active">Register</a>
<a *ngIf="!loggedIn" routerLink="/login" routerLinkActive="active">Login</a>
<a *ngIf="loggedIn" routerLink="/home" routerLinkActive="active">Home</a>
<a *ngIf="loggedIn" routerLink="/arena/file/new" routerLinkActive="active">Arena</a>
<a *ngIf="loggedIn" routerLink="/arena" routerLinkActive="active">Arena</a>
<a *ngIf="loggedIn" routerLink="/files" routerLinkActive="active">Files</a>
<a *ngIf="loggedIn" routerLink="/user" routerLinkActive="active">User</a>
</nav>
#compile-popup {
position: fixed;
top: calc(40vh - 100px);
top: 50%;
width: 30vw;
left: calc(35vw - 20px);
border-bottom: 1px solid #ddf;
padding: 20px;
background: #224;
transform: scale(0);
transform: translateY(-50%) scale(0);
opacity: 0;
transition: all 0.25s;
z-index: 1000;
&.open {
transform: none;
transform: translateY(-50%) scale(1);
opacity: 1;
}
}
......
......@@ -13,5 +13,5 @@
<textarea id="editor" name="editor" value="{{inp}}"></textarea>
</div>
<app-input (valueEmit)="updateInput($event)"></app-input>
<app-ide-compile [resultVal]="runCodeService.result" [statusVal]="runCodeService.status"></app-ide-compile>
<app-ide-compile [resultVal]="runCodeService.result" [statusVal]="runCodeService.runStatus"></app-ide-compile>
<app-save-file (savedFile)="isSaved = isUpToDate = true;" [file]="file"></app-save-file>
......@@ -55,7 +55,7 @@
@media screen and (max-width: 800px) {
.container {
padding: 20px 0px;
padding: 20px 0;
}
#attempt {
......
......@@ -106,6 +106,7 @@ int main() {
btn.innerHTML = 'Saved';
this.isUploading = false;
this.isUpToDate = true;
console.log(data);
}, error => {
console.log(error);
this.isUploading = false;
......
#input {
position: fixed;
top: calc(40vh - 100px);
top: 50%;
width: 30vw;
left: calc(35vw - 20px);
border-bottom: 1px solid #ddf;
padding: 20px;
background: #224;
transform: scale(0);
transform: translateY(-50%) scale(0);
opacity: 0;
transition: all 0.25s;
z-index: 1000;
&.open {
transform: none;
transform: translateY(-50%) scale(1);
opacity: 1;
}
}
......
......@@ -32,7 +32,7 @@ int main() {
return 0;
}</div>
Anyways, head on to the right section of the page to take the problem hands on, crack it ruthlessly and destroy the arrogance of the creator!`,
default_code: [`#include <iostream>
code: [`#include <iostream>
using namespace std;
int main() {
......@@ -43,6 +43,7 @@ int main() {
System.out.println("Hello, World!");
}
}`],
n_testcases: [5, 15]
});
}
......
......@@ -6,5 +6,6 @@ export interface Problem {
n_attempts: number;
n_correct: number;
problem_statement: string;
default_code: string[];
code: string[];
n_testcases: number[];
}
import {Injectable} from '@angular/core';
import {Problem} from './problem';
import {Observable, of, throwError} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class RunCodeService {
status = 'Compiling...';
runStatus = 'Compiling...';
result = 0;
constructor() {
......@@ -23,7 +25,7 @@ abcd
let time = 0;
for (const status of statusArray) {
setTimeout(() => {
this.status = status;
this.runStatus = status;
}, time);
time += 2000;
}
......@@ -32,4 +34,13 @@ abcd
this.result = 1;
}, 6000);
}
compileProblemFile(prob: Problem): Observable<string> {
if (Math.floor(Math.random() * 2) === 1) {return of('done'); }
else {return throwError('error'); }
}
tryTestcase(prob: Problem, index: number): Observable<boolean> {
return of(Math.floor(Math.random() * 2) === 1);
}
}
#save-popup {
position: fixed;
top: calc(40vh - 100px);
top: 50%;
width: 30vw;
left: calc(35vw - 20px);
border-bottom: 1px solid #ddf;
padding: 20px;
background: #224;
transform: scale(0);
transform: translateY(-50%) scale(0);
opacity: 0;
transition: all 0.25s;
z-index: 1000;
&.open {
transform: none;
transform: translateY(-50%) scale(1);
opacity: 1;
}
}
......
<div [class.open]="isActive" id="compile-cover"></div>
<div [class.open]="isActive" id="compile-popup">
<div id="testcase-grid">
<div *ngFor="let i of nts" class="testcase-status-div" [class.failed]="status[i] === -1" [class.successful]="status[i] === 1">Testcase {{i}}</div>
</div>
<div>
<button id="compile-done" (click)="isActive = false;">Done</button>
</div>
</div>
#compile-popup {
position: fixed;
top: 50%;
width: 50vw;
left: calc(25vw - 20px);
border-bottom: 1px solid #ddf;
padding: 20px;
background: #224;
transform: translateY(-50%) scale(0);
opacity: 0;
transition: all 0.25s;
z-index: 1000;
&.open {
transform: translateY(-50%) scale(1);
opacity: 1;
}
}
#compile-done {
float: right;
}
#compile-cover {
z-index: 999;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
display: none;
&.open {
display: block;
}
}
#testcase-grid {
display: grid;
grid-template-columns: auto auto auto;
}
.testcase-status-div {
margin: 10px;
padding: 10px;
display: flex;
justify-content: center;
color: #ddf;
border-bottom: 1px solid #ddf;
animation: blink 1s infinite;
&.failed {
animation: none;
border-color: #802;
background-color: #8028;
}
&.successful {
animation: none;
border-color:#082;
background-color: #0828;
}
}
@keyframes blink {
0%, 100% {
border-color: transparent;
}
50% {
border-color: #ddf;
}
}
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {TestcaseStatusComponent} from './testcase-status.component';
import { SubmitTryCodeComponent } from './submit-try-code.component';
describe('TestcaseStatusComponent', () => {
let component: TestcaseStatusComponent;
let fixture: ComponentFixture<TestcaseStatusComponent>;
describe('SubmitTryCodeComponent', () => {
let component: SubmitTryCodeComponent;
let fixture: ComponentFixture<SubmitTryCodeComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [TestcaseStatusComponent]
declarations: [ SubmitTryCodeComponent ]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(TestcaseStatusComponent);
fixture = TestBed.createComponent(SubmitTryCodeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
......
import {Component, Input, OnInit} from '@angular/core';
import {Problem} from '../problem';
import {RunCodeService} from '../run-code.service';
@Component({
selector: 'app-submit-try-code',
templateUrl: './submit-try-code.component.html',
styleUrls: ['./submit-try-code.component.scss']
})
export class SubmitTryCodeComponent implements OnInit {
isActive = false;
nts: number[];
status: number[];
@Input() problem: Problem;
submitting = 0;
constructor(public runCodeService: RunCodeService) { }
ngOnInit(): void { }
reset(): void {
this.nts = Array(this.problem.n_testcases[this.submitting]).fill(1).map((x, i) => i);
this.status = Array(this.problem.n_testcases[this.submitting]).fill(0);
for (const i of this.nts) {
this.runCodeService.tryTestcase(this.problem, i)
.subscribe(ret => {
this.status[i] = ret ? 1 : -1;
});
}
}
}
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'app-testcase-status',
templateUrl: './testcase-status.component.html',
styleUrls: ['./testcase-status.component.scss']
})
export class TestcaseStatusComponent implements OnInit {
constructor() {
}
ngOnInit(): void {
}
}
import {Problem} from './problem';
export interface User {
id: number;
username: string;
name: string;
password: string;
......@@ -10,5 +9,5 @@ export interface User {
n_attempts: number;
correct_timeline: string;
rating: number;
my_questions: Problem;
my_questions: Problem[];
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment