⏱ 0:02est. 23 min
Wrike
import React from "react";
import { useEffect } from "react/cjs/react.production.min";
import "./styles.css";
// Round 1
// websocket - half duplex or full?
// alternative of websocket
// react 16 error which lead to reload twice in dev mode. (React.strictMode on)
// clone json
//
/*
Write a component that displays the number of seconds left
until the date from the `date` variable.
*/
// Round 2 Build a counter application
// https://codesandbox.io/p/sandbox/react-timer-task-new-forked-6l88ng?file=%2Fsrc%2FApp.js%3A1%2C1-39%2C1
export default function App() {
const date = new Date(2025, 0, 1);
return <Countdown date={date} />;
}
function Countdown({ date }) {
let interval = null;
const [secondsLeft, setSecondsLeft] = React.useState(
(date.getTime() - new Date().getTime()) / 1000
);
React.useEffect(() => {
interval = setInterval(() => {
let time = (date.getTime() - new Date().getTime()) / 1000;
setSecondsLeft(time);
}, 1000);
return () => {
clearInterval(interval);
};
}, [date]);
return (
<div className={"div1"}>
Seconds left to {date.toLocaleDateString()}:
<div className="div2">{Math.ceil(secondsLeft)}</div>
</div>
);
}
// Round 3 - https://codesandbox.io/p/sandbox/wriketreestask-forked-4q59cw?file=%2Fsrc%2Futils.ts%3A6%2C1
// Q1. tree task
// SOL: https://www.geeksforgeeks.org/clone-binary-tree-random-pointers/
// trees-with-ref.ts
export interface TreeWithRef {
title: string;
child1: TreeWithRef | null;
child2: TreeWithRef | null;
randomRef: TreeWithRef | null;
}
export interface XTreeWithRef {
caption: string;
leaf1: XTreeWithRef | null;
leaf2: XTreeWithRef | null;
randomRef: XTreeWithRef | null;
}
export function copyWithRef(original: TreeWithRef | null): XTreeWithRef | null {
console.log("original", original);
// return JSON.parse(JSON.stringify(original));
let clone: TreeWithRef = {};
// 1. Create clone without randomRef
for (let prop in original) {
console.log(prop);
if (prop === "randomRef") {
// clone[prop] = clone[];
} else if (original[prop] === "object" && original[prop] != null) {
clone[prop] = copyWithRef(original[prop]);
} else {
clone[prop] = original[prop];
}
}
// 2. Clone - assing randomRef
for (let prop in original) {
console.log(prop);
if (prop === "randomRef") {
console.log("original[prop]?.title", original[prop]?.title);
clone[prop] = findRef(original[prop]?.title, clone);
}
}
return clone; // implement your copy here
}
function findRef(title: string, clone: TreeWithRef) {
if (!clone) {
return null;
}
if (title === clone.title) {
return clone;
}
findRef(title, clone?.child1);
findRef(title, clone?.child2);
}
export const runAdvancedTests = true;
// Solution1:
// index.js
import "./styles.css";
import { copy, Tree, XTree } from "./trees";
import {
copyWithRef,
runAdvancedTests,
TreeWithRef,
XTreeWithRef,
} from "./trees-with-ref";
import {
generateRandomTree,
generateRandomTreeWithRef,
compareStructure,
compareStructureWithRef,
} from "./utils";
var tree: Tree | null = generateRandomTree();
var treeWithRef: TreeWithRef | null = generateRandomTreeWithRef();
var ok_simple = false;
var ok_advanced = false;
// Simple Tree
try {
var xtree: XTree | null = copy(tree);
var ok_simple = compareStructure(tree, xtree);
} catch (e) {}
const simple = document.getElementById("simple");
simple!.innerText = ok_simple ? "Passed" : "Failed";
simple!.style.color = ok_simple ? "green" : "red";
//Advanced Tree (with ref) - UNCOMMENT BELOW ↓↓↓↓↓
if (runAdvancedTests) {
try {
var xtreeWithRef: XTreeWithRef | null = copyWithRef(treeWithRef);
var ok_advanced = compareStructureWithRef(treeWithRef, xtreeWithRef);
} catch (e) {}
const block = document.getElementById("advanced-block");
block!.style.display = "block";
const advanced = document.getElementById("advanced");
advanced!.innerText = ok_advanced ? "Passed" : "Failed";
advanced!.style.color = ok_advanced ? "green" : "red";
}
// util.js
import { TreeWithRef, XTreeWithRef } from "./trees-with-ref";
import { Tree, XTree } from "./trees";
var flatNodes: Array<TreeWithRef>;
var footprint: string;
export function generateRandomTree(lvl: number = 0): Tree | null {
if (lvl > 4 && Math.random() > 0.3) {
return null;
}
var child1 = generateRandomTree(lvl + 1);
var child2 = generateRandomTree(lvl + 1);
var node: Tree = {
title: "name_" + getRandomInt(9999),
child1: child1,
child2: child2,
};
return node;
}
export function compareStructure(tree: Tree | null, xtree: XTree | null) {
var treeString = JSON.stringify(tree);
var xtreeString = JSON.stringify(xtree)
.replaceAll("caption", "title")
.replaceAll("leaf1", "child1")
.replaceAll("leaf2", "child2");
//console.log("SIMPLE TESTS\n------- Tree Footprint -------\n"+treeString+"\n------- XTree Footprint -------\n"+xtreeString);
return treeString === xtreeString;
}
export function generateRandomTreeWithRef(): TreeWithRef | null {
flatNodes = [];
var root: TreeWithRef | null = generateTreeRefPass1();
for (var i = 0; i < flatNodes.length; i++) {
flatNodes[getRandomInt(flatNodes.length)].randomRef =
flatNodes[getRandomInt(flatNodes.length)];
}
flatNodes[10].randomRef = flatNodes[0];
flatNodes[0].randomRef = flatNodes[10];
return root;
}
function generateTreeRefPass1(lvl: number = 0): TreeWithRef | null {
if (lvl > 4 && Math.random() > 0.3) {
return null;
}
var child1 = generateTreeRefPass1(lvl + 1);
var child2 = generateTreeRefPass1(lvl + 1);
var node: TreeWithRef = {
title: "name_" + getRandomInt(9999),
child1: child1,
child2: child2,
randomRef: null,
};
flatNodes.push(node);
return node;
}
export function compareStructureWithRef(
treeWithRef: TreeWithRef | null,
xtreeWithRef: XTreeWithRef | null,
): boolean {
footprint = "";
getTreeWithRefFootprint(treeWithRef);
const treeString2 = footprint;
footprint = "";
getXTreeWithRefFootprint(xtreeWithRef);
const xtreeString2 = footprint;
// console.log(
// "ADVANCED TESTS\n------- TreeWithRef Footprint -------\n" +
// treeString2 +
// "\n------- XTreeWithRef Footprint -------\n" +
// xtreeString2,
// );
return treeString2 === xtreeString2;
}
function getTreeWithRefFootprint(tree: TreeWithRef | null) {
if (tree === null) return;
footprint +=
tree?.title +
", " +
tree.child1?.title +
", " +
tree.child2?.title +
", " +
tree.randomRef?.title +
"\n";
getTreeWithRefFootprint(tree?.child1);
getTreeWithRefFootprint(tree?.child2);
}
function getXTreeWithRefFootprint(tree: XTreeWithRef | null) {
if (tree === null) return;
footprint +=
tree?.caption +
", " +
tree.leaf1?.caption +
", " +
tree.leaf2?.caption +
", " +
tree.randomRef?.caption +
"\n";
getXTreeWithRefFootprint(tree?.leaf1);
getXTreeWithRefFootprint(tree?.leaf2);
}
function getRandomInt(max: number) {
return Math.floor(Math.random() * max);
}
// Round 3
// Q2. Review following code
```js
class Folder {
public Id: Number;
public Name: String;
public saveToDatabase(databaseName: String): void {
const c: Connection = new DataBaseConnection(databaseName).begin().connection;
if(this.Id != 0 && this.Name != null){c.write(this.Id+" : "+ this.Name);}
if(this.Id == 0 && this.Name != null){c.write(this.Name);}
if(this.Id != 0 && this.Name == null){c.write(this.Id);}
this.Name = this.Name + " saved";
}
}
class Group {
public Id: Number;
public Name: String;
public SaveToFile(f: String): void {
try {
const c: Connection = File.create(f);
if(this.Id == 0 && this.Name != null){c.write(this.Name);}
if(this.Id != 0 && this.Name == null){c.write(this.Id);}
if(this.Id != 0 && this.Name != null){c.write(this.Id+" : "+ this.Name);}
} catch(e) {
//DO nothing
}
//show message to user
VisualBox.show("Success!");
if(!checkThatFileExist(f)) throw new Error();
}
}
function main(): void {
const folder: Folder = new Folder();
folder.Name = "Test Fоlder";
const group: Group = new Group();
group.Id = "12345";
folder.saveToDatabase("TestDB");
group.SaveToFile("MyFile");
}
```
// Solution
class Folder {
public id: Number;
public name: String;
public saveToDatabase(databaseName: String, cb: Function): void {
const connection: Connection = new DataBaseConnection(databaseName).begin().connection; // moved out to create single instance
try {
if(this.id != 0 && this.name != null){
connection.write(this.id+" : "+ this.name);
connection.write(this.Id);
} else if (this.id == 0 && this.name != null){
connection.write(this.name);
}
cb("success")
} catch (err) {
cb("", err);
}
// if(this.Id != 0 && this.Name == null){}
this.Name = this.Name + " saved"; // This is logical err
}
}
class Group {
public id: Number;
public name: String;
public saveToFile(f: String): void {
try {
const connection: Connection = File.create(f); // moved out to create single instance
if(this.id == 0 && this.Name != null){c.write(this.Name);}
if(this.Id != 0 && this.Name == null){c.write(this.Id);}
if(this.Id != 0 && this.Name != null){c.write(this.Id+" : "+ this.Name);}
VisualBox.show("Success!");
} catch(e) {
//DO nothing
if(!checkThatFileExist(f)) throw new Error(e);
}
//show message to user
}
}
function main(): void {
const folder: Folder = new Folder();
folder.Name = "Test Fоlder"; // TODO: pass this name in constructor, rename Name to name
const group: Group = new Group();
group.Id = "12345"; // TODO: pass this id in constructor, rename Id to id
group.saveToFile("MyFile"); // TODO: change to saveToFile
folder.saveToDatabase("TestDB");
}