Skip to content

Commit 507ea50

Browse files
author
Abylkasym uulu Alidin
committed
show history button added for frontend
1 parent 7876bc8 commit 507ea50

File tree

2 files changed

+173
-29
lines changed

2 files changed

+173
-29
lines changed

time_complexity_analyzer/frontend/src/components/CalculatorPage.js

Lines changed: 171 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
import React, { useState, useEffect } from "react";
2-
import { Container, Card, CardContent, Button, Select, MenuItem, Typography, FormControl, InputLabel, Box } from "@mui/material";
2+
import {
3+
Container,
4+
Card,
5+
CardContent,
6+
Button,
7+
Select,
8+
MenuItem,
9+
Typography,
10+
FormControl,
11+
InputLabel,
12+
Box,
13+
} from "@mui/material";
314
import CodeEditorArea from "./CodeEditorArea";
415
import Output from "./CodeOut";
516
import AxiosInstance from "./Axios";
@@ -26,7 +37,7 @@ const time_complexity_notation = {
2637
subexponential_variant: "2^(o(n))",
2738
polynomial_linear_exponent: "O(2^(O(n)))",
2839
double_exponential: "O(2^(2^n))",
29-
exponential_poly: "O(2^(poly(n)))"
40+
exponential_poly: "O(2^(poly(n)))",
3041
};
3142

3243
const limitations = {
@@ -37,7 +48,7 @@ const limitations = {
3748
"Only one function should be present",
3849
"No third-party libraries",
3950
"No empty lines or comments",
40-
"Code will be run with the numbers between 0 and 10^3"
51+
"Code will be run with the numbers between 0 and 10^5",
4152
],
4253
Python: [
4354
"Function must accept a list as an argument",
@@ -46,26 +57,32 @@ const limitations = {
4657
"Only one function should be present",
4758
"No third-party libraries",
4859
"No empty lines or comments",
49-
"Code will be run with the numbers between 0 and 10^3"
60+
"Code will be run with the numbers between 0 and 10^5",
5061
],
5162
Cpp: [
5263
"Function must be defined as: type functionName(std::vector<int>& arr)",
5364
"No public or private keywords",
5465
"Only one function should be present",
5566
"No third-party libraries",
5667
"No empty lines or comments",
57-
"Code will be run with the numbers between 0 and 10^3"
58-
]
68+
"Code will be run with the numbers between 0 and 10^5",
69+
],
5970
};
6071

6172
function CalculatorPage({ isAuthenticated, currentUser }) {
6273
const [code, setCode] = useState(``);
6374
const [language, setLanguage] = useState("Python");
64-
const [outputText, setOutputText] = useState("// Output will be displayed here");
75+
const [outputText, setOutputText] = useState(
76+
"// Output will be displayed here"
77+
);
6578
const [results, setResults] = useState([]);
79+
const [history, setHistory] = useState([]);
6680
const [error, setError] = useState("");
6781
const [userModifiedCode, setUserModifiedCode] = useState(false);
6882
const [loading, setLoading] = useState(false);
83+
const [showHistory, setShowHistory] = useState(false);
84+
const [expandedCode, setExpandedCode] = useState(null);
85+
const [historyLoading, setHistoryLoading] = useState(false);
6986
const user = isAuthenticated ? currentUser : "Unknown";
7087

7188
const defaultCodes = {
@@ -115,6 +132,34 @@ function CalculatorPage({ isAuthenticated, currentUser }) {
115132
setUserModifiedCode(true);
116133
};
117134

135+
const fetchHistory = () => {
136+
if (isAuthenticated) {
137+
setHistoryLoading(true);
138+
AxiosInstance.get(`/code-history/${user}/`)
139+
.then((response) => {
140+
const nonEmptyResults = response.data.filter(
141+
(entry) =>
142+
entry.analysis_result &&
143+
Object.keys(entry.analysis_result).length > 0
144+
);
145+
setHistory(nonEmptyResults);
146+
setHistoryLoading(false);
147+
})
148+
.catch(() => {
149+
setHistoryLoading(false);
150+
});
151+
}
152+
};
153+
154+
const handleToggleHistory = () => {
155+
setShowHistory((prev) => {
156+
if (!prev) {
157+
fetchHistory();
158+
}
159+
return !prev;
160+
});
161+
};
162+
118163
const handleAnalyseClick = () => {
119164
if (!user || !code || !language) {
120165
setError("Can't calculate it. Please check your code and try again.");
@@ -128,7 +173,7 @@ function CalculatorPage({ isAuthenticated, currentUser }) {
128173
username: user,
129174
code: code,
130175
language: language,
131-
time_complexity: "O(n)"
176+
time_complexity: "O(n)",
132177
};
133178

134179
AxiosInstance.post("/api/analyse-code/", payload)
@@ -138,7 +183,7 @@ function CalculatorPage({ isAuthenticated, currentUser }) {
138183
setError("");
139184
setLoading(false);
140185
})
141-
.catch((error) => {
186+
.catch(() => {
142187
setError("Can't calculate it. Please check your code and try again.");
143188
setLoading(false);
144189
});
@@ -147,25 +192,36 @@ function CalculatorPage({ isAuthenticated, currentUser }) {
147192
const formatResults = (data, code) => {
148193
const codeLines = code.split("\n");
149194
const results = codeLines.map((line, index) => {
150-
const lineInfo = data.lines ? data.lines[language === 'Python' ? index : index + 1] : null;
195+
const lineInfo = data.lines ? data.lines[index] : null;
151196
if (lineInfo) {
152197
const complexity = lineInfo.best_fit ? lineInfo.best_fit.model : "";
153198
const avgExecTimes = lineInfo.average_exec_times || {};
154199
return {
155200
line: line.trim(),
156201
complexity,
157202
notation: time_complexity_notation[complexity] || "",
158-
avgExecTimes
203+
avgExecTimes,
159204
};
160205
}
161-
return { line: line.trim(), function: "", complexity: "", avgExecTimes: {} };
206+
return {
207+
line: line.trim(),
208+
function: "",
209+
complexity: "",
210+
avgExecTimes: {},
211+
};
162212
});
163213

164-
const functionComplexity = data.function && data.function.best_fit ? data.function.best_fit.model : "";
165-
const functionAvgExecTimes = data.function ? data.function.average_exec_times : {};
214+
const functionComplexity =
215+
data.function && data.function.best_fit
216+
? data.function.best_fit.model
217+
: "";
218+
const functionAvgExecTimes = data.function
219+
? data.function.average_exec_times
220+
: {};
166221
results.functionComplexity = functionComplexity;
167222
results.functionComplexityWord = functionComplexity;
168-
results.functionNotation = time_complexity_notation[functionComplexity] || "";
223+
results.functionNotation =
224+
time_complexity_notation[functionComplexity] || "";
169225
results.functionAvgExecTimes = functionAvgExecTimes;
170226

171227
return results;
@@ -174,31 +230,89 @@ function CalculatorPage({ isAuthenticated, currentUser }) {
174230
const formatOutput = (data, code) => {
175231
const codeLines = code.split("\n");
176232
const linesOutput = codeLines.map((line, index) => {
177-
const lineInfo = data.lines ? data.lines[language === 'Python' ? index : index + 1] : null;
233+
const lineInfo = data.lines ? data.lines[index] : null;
178234
if (lineInfo) {
179-
const avgExecTimes = lineInfo.average_exec_times
180-
? Object.entries(lineInfo.average_exec_times).map(([size, time]) => `${size}: ${time.toFixed(2)} ns`).join(", ")
235+
const avgExecTimes = lineInfo.average_exec_times
236+
? Object.entries(lineInfo.average_exec_times)
237+
.map(([size, time]) => `${size}: ${time.toFixed(2)} ns`)
238+
.join(", ")
181239
: "";
182-
return `${line} -> ${time_complexity_notation[lineInfo.best_fit ? lineInfo.best_fit.model : ""] || ""} {${lineInfo.best_fit ? lineInfo.best_fit.model : ""}} (Avg times: ${avgExecTimes})`;
240+
return `${line} -> ${
241+
time_complexity_notation[
242+
lineInfo.best_fit ? lineInfo.best_fit.model : ""
243+
] || ""
244+
} {${
245+
lineInfo.best_fit ? lineInfo.best_fit.model : ""
246+
}} (Avg times: ${avgExecTimes})`;
183247
}
184248
return line;
185249
});
186250

187-
const overallAvgExecTimes = data.function && data.function.average_exec_times
188-
? Object.entries(data.function.average_exec_times).map(([size, time]) => `${size}: ${time.toFixed(2)} ns`).join(", ")
189-
: "";
251+
const overallAvgExecTimes =
252+
data.function && data.function.average_exec_times
253+
? Object.entries(data.function.average_exec_times)
254+
.map(([size, time]) => `${size}: ${time.toFixed(2)} ns`)
255+
.join(", ")
256+
: "";
190257
const overallComplexity = data.function
191-
? `\nOverall Function Time Complexity: ${time_complexity_notation[data.function.best_fit ? data.function.best_fit.model : ""] || ""} {${data.function.best_fit ? data.function.best_fit.model : ""}} (Avg times: ${overallAvgExecTimes})`
258+
? `\nOverall Function Time Complexity: ${
259+
time_complexity_notation[
260+
data.function.best_fit ? data.function.best_fit.model : ""
261+
] || ""
262+
} {${
263+
data.function.best_fit ? data.function.best_fit.model : ""
264+
}} (Avg times: ${overallAvgExecTimes})`
192265
: "";
193266
linesOutput.push(overallComplexity);
194267
return linesOutput.join("\n");
195268
};
196269

270+
const renderHistory = () => {
271+
if (historyLoading) {
272+
return <Typography>Loading history...</Typography>;
273+
}
274+
275+
if (!history || history.length === 0) {
276+
return <Typography>No history available.</Typography>;
277+
}
278+
279+
return history.map((entry, index) => (
280+
<Card key={index} className="mt-2">
281+
<CardContent>
282+
<Typography
283+
variant="h6"
284+
style={{
285+
cursor: "pointer",
286+
textDecoration: "underline",
287+
color: "blue",
288+
}}
289+
onClick={() =>
290+
setExpandedCode(expandedCode === index ? null : index)
291+
}
292+
>
293+
{`Code (${entry.language}) - ${entry.code.slice(0, 50)}...`}
294+
</Typography>
295+
{expandedCode === index && (
296+
<Output
297+
outputText=""
298+
results={formatResults(entry.analysis_result, entry.code)}
299+
error=""
300+
loading={false}
301+
/>
302+
)}
303+
<Typography variant="caption">{`Analyzed on: ${new Date(
304+
entry.created_at
305+
).toLocaleString()}`}</Typography>
306+
</CardContent>
307+
</Card>
308+
));
309+
};
310+
197311
return (
198312
<Container sx={{ maxWidth: "1800px" }}>
199313
<Card className="mt-4">
200314
<CardContent>
201-
<Box display="flex" justifyContent="center">
315+
<Box display="flex" justifyContent="space-between">
202316
<FormControl variant="outlined" sx={{ width: 200 }}>
203317
<InputLabel id="language-select-label">Language</InputLabel>
204318
<Select
@@ -212,21 +326,50 @@ function CalculatorPage({ isAuthenticated, currentUser }) {
212326
<MenuItem value="Cpp">C++</MenuItem>
213327
</Select>
214328
</FormControl>
329+
<Button
330+
variant="contained"
331+
color="secondary"
332+
onClick={handleToggleHistory}
333+
disabled={!isAuthenticated}
334+
>
335+
{showHistory ? "Hide History" : "Show History"}
336+
</Button>
215337
</Box>
216338
</CardContent>
217339
</Card>
218-
<div className="flex flex-row mt-3" style={{ display: "flex", width: "100%" }}>
340+
<div
341+
className="flex flex-row mt-3"
342+
style={{ display: "flex", width: "100%" }}
343+
>
219344
<Card className="flex-grow-1" sx={{ flex: 1, marginRight: "1rem" }}>
220345
<CardContent>
221-
<CodeEditorArea language={language} code={code} onCodeChange={handleCodeChange} />
222-
<Button variant="contained" color="primary" className="mt-4" onClick={handleAnalyseClick}>
346+
<CodeEditorArea
347+
language={language}
348+
code={code}
349+
onCodeChange={handleCodeChange}
350+
/>
351+
<Button
352+
variant="contained"
353+
color="primary"
354+
className="mt-4"
355+
onClick={handleAnalyseClick}
356+
>
223357
Analyse
224358
</Button>
225359
</CardContent>
226360
</Card>
227361
<Card className="flex-grow-2" sx={{ flex: 3 }}>
228362
<CardContent>
229-
<Output outputText={outputText} results={results} error={error} loading={loading} />
363+
{showHistory ? (
364+
renderHistory()
365+
) : (
366+
<Output
367+
outputText={outputText}
368+
results={results}
369+
error={error}
370+
loading={loading}
371+
/>
372+
)}
230373
</CardContent>
231374
</Card>
232375
</div>

time_complexity_analyzer/requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ pytest-django>=4.1
66
djangorestframework-simplejwt>=4.8
77
django-cors-headers>=3.7
88
numpy>=1.21.0
9-
scipy>=1.7.0
9+
scipy>=1.7.0
10+
numpy==2.0.1

0 commit comments

Comments
 (0)