diff --git a/server/package-lock.json b/server/package-lock.json index 1c50223..8f49fe5 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -20,6 +20,7 @@ "md5": "^2.3.0", "mongoose": "^7.6.2", "mongoose-autopopulate": "^1.1.0", + "pattern-matching-ts": "^2.0.0", "pm2": "^5.3.1", "reflect-metadata": "^0.1.13", "rimraf": "^5.0.5", @@ -27,6 +28,7 @@ "socket.io-client": "^4.7.2", "spark-md5": "^3.0.2", "ts-md5": "^1.3.1", + "ts-pattern": "^5.1.1", "tsc-watch": "^6.0.4", "uuid": "^9.0.1" }, @@ -6224,6 +6226,11 @@ "node": ">= 14.16" } }, + "node_modules/pattern-matching-ts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pattern-matching-ts/-/pattern-matching-ts-2.0.0.tgz", + "integrity": "sha512-XfNA/wZ1A92Ps+jzlmFKXviAI6YQt98GwZoHVAsDEMOKYo+g5aSjvMQ3lnvYQskIYdBj30r7S4rAx/VzuxsRhA==" + }, "node_modules/pause-stream": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", @@ -7781,6 +7788,11 @@ "node": ">=0.3.1" } }, + "node_modules/ts-pattern": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.1.1.tgz", + "integrity": "sha512-i+owkHr5RYdQxj8olUgRrqpiWH9x27PuWVfXwDmJ/n/CoF/SAa7WW1i2oUpPDMQpJ4U+bGRUcZkVq7i1m3zFCg==" + }, "node_modules/tsc-watch": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-6.0.4.tgz", diff --git a/server/package.json b/server/package.json index 45cb42d..ab14540 100644 --- a/server/package.json +++ b/server/package.json @@ -24,13 +24,13 @@ "chai": "latest", "eslint": "^8.47.0", "mocha": "latest", + "node-watch": "^0.7.4", + "nodemon": "^3.0.1", "nyc": "latest", "source-map-support": "latest", "ts-node": "^10.9.1", "tslint": "latest", - "typescript": "^5.1.6", - "node-watch": "^0.7.4", - "nodemon": "^3.0.1" + "typescript": "^5.1.6" }, "dependencies": { "@grpc/grpc-js": "^1.9.0", @@ -45,6 +45,7 @@ "md5": "^2.3.0", "mongoose": "^7.6.2", "mongoose-autopopulate": "^1.1.0", + "pattern-matching-ts": "^2.0.0", "pm2": "^5.3.1", "reflect-metadata": "^0.1.13", "rimraf": "^5.0.5", @@ -52,6 +53,7 @@ "socket.io-client": "^4.7.2", "spark-md5": "^3.0.2", "ts-md5": "^1.3.1", + "ts-pattern": "^5.1.1", "tsc-watch": "^6.0.4", "uuid": "^9.0.1" } diff --git a/server/src/core/extensions/extensions.ts b/server/src/core/extensions/extensions.ts index b945e51..3720a4f 100644 --- a/server/src/core/extensions/extensions.ts +++ b/server/src/core/extensions/extensions.ts @@ -21,6 +21,8 @@ declare global { hasPattern(pattern: string): boolean; hasNoPattern(pattern: string): boolean; pathNormalize(): string; + isEqual(str: string): boolean; + isEqualMany(str: string[]): boolean; } } export const extensions = () => { diff --git a/server/src/core/extensions/string.ts b/server/src/core/extensions/string.ts index a05eee1..eea688d 100644 --- a/server/src/core/extensions/string.ts +++ b/server/src/core/extensions/string.ts @@ -31,4 +31,19 @@ export const StringExtensions = () => { return !this.hasPattern(pattern); }; } + if ("".isEqual === undefined) { + String.prototype.isEqual = function (str: string) { + return this === str; + }; + } + if ("".isEqualMany === undefined) { + String.prototype.isEqualMany = function (str: string[]) { + for (const el of str) { + if (el === this) { + return true; + } + } + return false; + }; + } }; diff --git a/server/src/features/weights/domain/exec_weights_process_scenario.ts b/server/src/features/weights/domain/exec_weights_process_scenario.ts index b60e8a5..e22e254 100644 --- a/server/src/features/weights/domain/exec_weights_process_scenario.ts +++ b/server/src/features/weights/domain/exec_weights_process_scenario.ts @@ -6,29 +6,37 @@ import { ReadByIdDataBaseModelUseCase } from "../../../core/usecases/read_by_id_ import { MongoIdValidation } from "../../../core/validations/mongo_id_validation"; import { ProcessWatcherAndDatabaseUpdateService } from "../../datasets/domain/create_dataset_scenario"; import { WeightDBModel, IWeightModel } from "../models/weights_validation_model"; +import { match } from "ts-pattern"; export class ExecWeightProcessScenario extends CallbackStrategyWithIdQuery { idValidationExpression = new MongoIdValidation(); - call = async (id: string): ResponseBase => { - return (await new ReadByIdDataBaseModelUseCase(WeightDBModel).call(id)).map(async (model) => { + call = async (id: string): ResponseBase => + (await new ReadByIdDataBaseModelUseCase(WeightDBModel).call(id)).map(async (model) => { return (await new IsHaveActiveProcessUseCase().call()).map(async () => { await WeightDBModel.findById(id).updateOne({ processStatus: "RUN" }); + return match(model.processStatus) + .with("exec", "RUN", "none", () => this.exec(id, model, true)) + .with("new", () => this.exec(id, model, false)) + .otherwise(() => Result.error(`model status is ${model.processStatus}`)); + }); + }); + + exec = (id: string, model: IWeightModel, preTrain: boolean) => + match(typeof model.project === "object" && typeof model.datasetId === "object") + .returnType() + .with(true, async () => { if (typeof model.project === "object" && typeof model.datasetId === "object") { - if (model.processStatus === "exec") { - console.log(20); - } - if (model.processStatus === "new") { - console.log(20); - } - return new ExecProcessUseCase().call( + console.log( `${model.project.rootDir}/`, - `python3 $PYTHON_EDUCATION --path ${model.project.rootDir} --name ${model.name} --datasetName ${model.datasetId.name} --outpath ${model.project.rootDir} --type ${model.datasetId.formBuilder.output.typedataset} --epoch ${model.epoch} `, + `python3 $PYTHON_EDUCATION --path ${model.project.rootDir} --name ${model.name} --datasetName ${model.datasetId.name} --outpath ${model.project.rootDir} --type ${model.datasetId.formBuilder.output.typedataset} --epoch ${model.epoch} --pretrain ${preTrain}` + ); + return await new ExecProcessUseCase().call( + `${model.project.rootDir}/`, + `python3 $PYTHON_EDUCATION --path ${model.project.rootDir} --name ${model.name} --datasetName ${model.datasetId.name} --outpath ${model.project.rootDir} --type ${model.datasetId.formBuilder.output.typedataset} --epoch ${model.epoch} --pretrain ${preTrain}`, id, new ProcessWatcherAndDatabaseUpdateService(id as unknown as ObjectId, WeightDBModel) ); } - return Result.error("model project is not object"); - }); - }); - }; + }) + .with(false, async () => Result.error("model is unknown")); } diff --git a/server/src/features/weights/models/weights_database_model.ts b/server/src/features/weights/models/weights_database_model.ts index 67358c6..82efc82 100644 --- a/server/src/features/weights/models/weights_database_model.ts +++ b/server/src/features/weights/models/weights_database_model.ts @@ -2,7 +2,6 @@ import { IsNumber, IsString } from "class-validator"; import { IWeightModel } from "./weights_validation_model"; export class WeightValidationModel implements IWeightModel { - @IsNumber() public numberOfTrainedEpochs: number; public processStatus: string; @IsNumber() diff --git a/server/src/main.ts b/server/src/main.ts index 31a841e..ec6b250 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -5,9 +5,10 @@ import { extensions } from "./core/extensions/extensions"; import { httpRoutes } from "./core/controllers/routes"; import { executorProgramService } from "./core/usecases/exec_process_usecase"; - extensions(); const socketSubscribers = [new SocketSubscriber(executorProgramService, "realtime")]; new App(httpRoutes, socketSubscribers).listen(); + + diff --git a/ui/package-lock.json b/ui/package-lock.json index 656fe65..46b9d00 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -25,6 +25,7 @@ "mobx": "^6.10.0", "mobx-react-lite": "^4.0.4", "mobx-store-inheritance": "^1.0.6", + "pattern-matching-ts": "^2.0.0", "react": "^18.2.0", "react-accessible-treeview": "^2.8.3", "react-dnd": "^16.0.1", @@ -45,8 +46,8 @@ "three": "^0.159.0", "three-stdlib": "^2.28.9", "three-transform-controls": "^1.0.4", - "ts-pattern": "^5.0.6", - "typescript": "^4.9.5", + "ts-pattern": "^5.1.1", + "typescript": "^5.4", "urdf-loader": "^0.12.1", "uuid": "^9.0.1", "web-vitals": "^2.1.4", @@ -11625,18 +11626,6 @@ "mobx": "^6" } }, - "node_modules/mobx-store-inheritance/node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", @@ -12206,6 +12195,11 @@ "node": ">=8" } }, + "node_modules/pattern-matching-ts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pattern-matching-ts/-/pattern-matching-ts-2.0.0.tgz", + "integrity": "sha512-XfNA/wZ1A92Ps+jzlmFKXviAI6YQt98GwZoHVAsDEMOKYo+g5aSjvMQ3lnvYQskIYdBj30r7S4rAx/VzuxsRhA==" + }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -17016,9 +17010,9 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, "node_modules/ts-pattern": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.0.6.tgz", - "integrity": "sha512-Y+jOjihlFriWzcBjncPCf2/am+Hgz7LtsWs77pWg5vQQKLQj07oNrJryo/wK2G0ndNaoVn2ownFMeoeAuReu3Q==" + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.1.1.tgz", + "integrity": "sha512-i+owkHr5RYdQxj8olUgRrqpiWH9x27PuWVfXwDmJ/n/CoF/SAa7WW1i2oUpPDMQpJ4U+bGRUcZkVq7i1m3zFCg==" }, "node_modules/tsconfig-paths": { "version": "3.15.0", @@ -17186,15 +17180,15 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/unbox-primitive": { diff --git a/ui/package.json b/ui/package.json index 8a23e6b..62039e4 100644 --- a/ui/package.json +++ b/ui/package.json @@ -20,6 +20,7 @@ "mobx": "^6.10.0", "mobx-react-lite": "^4.0.4", "mobx-store-inheritance": "^1.0.6", + "pattern-matching-ts": "^2.0.0", "react": "^18.2.0", "react-accessible-treeview": "^2.8.3", "react-dnd": "^16.0.1", @@ -40,8 +41,8 @@ "three": "^0.159.0", "three-stdlib": "^2.28.9", "three-transform-controls": "^1.0.4", - "ts-pattern": "^5.0.6", - "typescript": "^4.9.5", + "ts-pattern": "^5.1.1", + "typescript": "^5.4", "urdf-loader": "^0.12.1", "uuid": "^9.0.1", "web-vitals": "^2.1.4", diff --git a/ui/src/features/scene_manager/presentation/scene_manager_store.ts b/ui/src/features/scene_manager/presentation/scene_manager_store.ts index a2f0be2..7e38487 100644 --- a/ui/src/features/scene_manager/presentation/scene_manager_store.ts +++ b/ui/src/features/scene_manager/presentation/scene_manager_store.ts @@ -1,6 +1,6 @@ import makeAutoObservable from "mobx-store-inheritance"; -import { CoreThreeRepository, UserData } from "../../../core/repository/core_three_repository"; -import { Object3D, Vector2, Vector3 } from "three"; +import { CoreThreeRepository } from "../../../core/repository/core_three_repository"; +import { Object3D, Vector2 } from "three"; import { HttpError } from "../../../core/repository/http_repository"; import { UiErrorState } from "../../../core/store/base_store"; import { UiBaseError } from "../../../core/model/ui_base_error"; diff --git a/ui/src/features/skils/skill_card.tsx b/ui/src/features/skils/skill_card.tsx index 3cfb7d4..57e9c5d 100644 --- a/ui/src/features/skils/skill_card.tsx +++ b/ui/src/features/skils/skill_card.tsx @@ -5,6 +5,7 @@ import { CoreText, CoreTextType } from "../../core/ui/text/text"; import { ProcessStatus } from "../dataset/dataset_model"; import { IMenuItem } from "../dataset/card_dataset"; import type { MenuProps } from "antd"; +import { match } from "ts-pattern"; export interface ISkillCardProps { processStatus?: string; @@ -16,7 +17,9 @@ export interface ISkillCardProps { continueOnClick?: (id: string) => void; empty: boolean; onEdit?: (id: string) => void; + epoch?: number; onDelete?: (id: string) => void; + datasetName?: string; } export const SkillCard = (props: ISkillCardProps) => { @@ -34,7 +37,7 @@ export const SkillCard = (props: ISkillCardProps) => { name: "Удалить", }, ]; - + const items: MenuProps["items"] = menu.map((el, index) => { return { key: String(index), @@ -58,92 +61,132 @@ export const SkillCard = (props: ISkillCardProps) => { justifyContent: "space-between", }} > - {props.empty ? ( -
{ - if (props.empty && props.emptyOnClick) props.emptyOnClick(); - }} - style={{ display: "flex", justifyContent: "center", alignItems: "center" }} - > - -
- ) : ( - <> -
- - -
- -
-
-
-
-
- {props.processStatus === ProcessStatus.NONE ? ( - <> - { - if (props.startOnClick && props.id) props.startOnClick(props.id); - }} - /> -
- { - if (props.continueOnClick && props.id) props.continueOnClick(props.id); - }} - /> - - ) : null} - {props.processStatus === ProcessStatus.END ? ( - <> - { - if (props.startOnClick && props.id) props.startOnClick(props.id); - }} - /> -
- { - if (props.continueOnClick && props.id) props.continueOnClick(props.id); - }} - /> - - ) : null} - {props.processStatus === ProcessStatus.RUN ? ( - <> - { - // if (props.type.isEqual(CardDataSetType.COMPLETED) && props.onClickButton && props.id) { - // props.onClickButton(props.id); - }} - block={true} - text="Стоп" - /> - - ) : null} - {props.processStatus === ProcessStatus.ERROR ? ( - ( + <> +
{ + if (props.empty && props.emptyOnClick) props.emptyOnClick(); + }} + style={{ display: "flex", justifyContent: "center", alignItems: "center" }} + > + +
+ + )) + .with(false, () => ( + <> + <> +
{}} - filled={true} - text="Ошибка" - /> - ) : null} -
- - )} + > +
+ +
+ + +
+
+ +
+ +
+
+
+
+
+
+ {match(props.processStatus) + .with(ProcessStatus.END, () => ( + <> + { + if (props.startOnClick && props.id) props.startOnClick(props.id); + }} + /> + { + if (props.startOnClick && props.id) props.startOnClick(props.id); + }} + /> + + )) + .with(ProcessStatus.NONE, () => ( + <> + { + if (props.startOnClick && props.id) props.startOnClick(props.id); + }} + /> + + )) + + .otherwise(() => ( + <> + ))} +
+ + + )) + .otherwise(() => ( + <> + ))}
); }; +// {props.processStatus === ProcessStatus.NONE ? ( +// <> +//
+// { +// if (props.continueOnClick && props.id) props.continueOnClick(props.id); +// }} +// /> +// +// ) : null} +// {props.processStatus === ProcessStatus.END ? ( +// <> +// { +// if (props.startOnClick && props.id) props.startOnClick(props.id); +// }} +// /> +//
+// { +// if (props.continueOnClick && props.id) props.continueOnClick(props.id); +// }} +// /> +// +// ) : null} +// {props.processStatus === ProcessStatus.RUN ? ( +// <> +// { +// // if (props.type.isEqual(CardDataSetType.COMPLETED) && props.onClickButton && props.id) { +// // props.onClickButton(props.id); +// }} +// block={true} +// text="Стоп" +// /> +// +// ) : null} +// {props.processStatus === ProcessStatus.ERROR ? ( +// {}} +// filled={true} +// text="Ошибка" +// /> +// ) : null} diff --git a/ui/src/features/skils/skill_model.ts b/ui/src/features/skils/skill_model.ts index 0eb72fc..1cd6b80 100644 --- a/ui/src/features/skils/skill_model.ts +++ b/ui/src/features/skils/skill_model.ts @@ -1,10 +1,22 @@ import makeAutoObservable from "mobx-store-inheritance"; import { Result } from "../../core/helper/result"; +import { ISkils } from "./skills_repository"; export class SkillModel { - constructor(public name: string, public datasetId: string, public project: string, public epoch: number) { + numberOfTrainedEpochs?: number; + constructor( + public name: string, + public datasetId: string, + public project: string, + public epoch: number, + numberOfTrainedEpochs?: number + ) { + this.numberOfTrainedEpochs = numberOfTrainedEpochs; makeAutoObservable(this); } + static fromISkill(model: ISkils) { + return new SkillModel(model.name, model.datasetId._id, model.project._id, model.epoch, model.numberOfTrainedEpochs); + } static empty() { return new SkillModel("", "", "", 0); } diff --git a/ui/src/features/skils/skills_repository.tsx b/ui/src/features/skils/skills_repository.tsx index 083a5de..a8d020a 100644 --- a/ui/src/features/skils/skills_repository.tsx +++ b/ui/src/features/skils/skills_repository.tsx @@ -8,9 +8,11 @@ export interface ISkils { _id: string; name: string; processStatus: string; + epoch:number; isFinished: boolean; datasetId: any; project: any; + numberOfTrainedEpochs:number; __v: number; } diff --git a/ui/src/features/skils/skills_screen.tsx b/ui/src/features/skils/skills_screen.tsx index 0ae2294..1505431 100644 --- a/ui/src/features/skils/skills_screen.tsx +++ b/ui/src/features/skils/skills_screen.tsx @@ -48,12 +48,31 @@ export const SkillScreen = observer(() => { }} > {store.skils?.map((el) => ( - store.execSkill(id)} continueOnClick={(id) => store.continueSkill(id)} /> + store.execSkill(id)} + continueOnClick={(id) => store.continueSkill(id)} + onEdit={(id) => store.editSkill(id)} + /> ))} store.edtDrawer(DrawersSkill.NEW_SKILL, true)} />
} /> + store.edtDrawer(DrawersSkill.EDIT_SKILL, false)} + open={store.drawers.find((el) => el.name === DrawersSkill.EDIT_SKILL)?.status} + > + + { + editSkill(id: string): void { + this.skill = SkillModel.fromISkill(this.getSkillById(id) as ISkils); + + this.edtDrawer(DrawersSkill.EDIT_SKILL, true); + } drawers: Drawer[]; skillsHttpRepository: SkillsHttpRepository; skils?: ISkils[]; @@ -66,17 +72,19 @@ export class SkillStore extends UiErrorState { } changeEpoch(epoch: number) { this.skill.epoch = epoch; + } saveSkill() { this.skill.project = this.activeProjectId?.id ?? ""; this.skill.valid().fold( async (model) => { (await this.skillsHttpRepository.addNewSkill(model)).fold( - (s) => { + async (s) => { message.success("Новый "); this.skill = SkillModel.empty(); + await this.mapOk("skils", this.skillsHttpRepository.getAllSkills()); }, - (e) => message.error(e.message) + async (e) => message.error(e.message) ); }, async (e) => message.error(e) diff --git a/web_p/education.py b/web_p/education.py index ac60d5e..438af71 100644 --- a/web_p/education.py +++ b/web_p/education.py @@ -11,6 +11,7 @@ parser.add_argument("--datasetName", required=True, help="String with dataset na parser.add_argument("--outpath", default="weights", help="Output path for weights") parser.add_argument("--type", default="ObjectDetection", help="Type of implementation") parser.add_argument("--epoch", default=3, help="How many training epochs") +parser.add_argument('--pretrain', help="Use pretraining") args = parser.parse_args() @@ -28,5 +29,4 @@ def copy_and_move_folder(src, dst, folder): source_folder = os.path.dirname(os.path.abspath(__file__)) + "/education" - copy_and_move_folder(source_folder, args.path, args.name)