progress machine learning screen

This commit is contained in:
IDONTSUDO 2024-07-26 18:50:36 +03:00
parent 0b3eefec2d
commit d41310196f
24 changed files with 428 additions and 231 deletions

View file

@ -0,0 +1,22 @@
import { Result } from "../helper/result";
import { validate, ValidationError } from "class-validator";
export class ValidationModel {
valid = async (): Promise<Result<string, ValidationModel>> => {
const errors: ValidationError[] = await validate(this, {
skipMissingProperties: false,
whitelist: false,
forbidNonWhitelisted: true,
});
if (errors.isNotEmpty()) {
const message = errors.map((error: ValidationError) => {
if (error.constraints) return Object.values(error.constraints).join(", ");
return "";
});
return Result.error(message.join(","));
} else {
return Result.ok(this);
}
};
}

View file

@ -10,7 +10,7 @@ import { DataSetScreen, DatasetsScreenPath } from "../../features/dataset/datase
import { AssemblesScreen, AssemblesScreenPath } from "../../features/assembles/assembles_screen";
import { SimulationScreen, SimulationScreenPath } from "../../features/simulations/simulations_screen";
import { EstimateScreen, EstimateScreenPath } from "../../features/estimate/estimate_screen";
import { SkillPath, SkillScreen } from "../../features/skils/skills_screen";
import { MachineLearningPath, MachineLearningScreen } from "../../features/machine_learning/presentation/machine_learning_screen";
import { DetailsScreenPath, DetailsScreen } from "../../features/details/details_screen";
const idURL = ":id";
@ -57,7 +57,7 @@ export const router = createBrowserRouter([
element: <EstimateScreen />,
},
{
path: SkillPath,
element: <SkillScreen />,
path: MachineLearningPath,
element: <MachineLearningScreen />,
},
]);

View file

@ -7,6 +7,7 @@ import { CoreSelect } from "../select/select";
import { CoreInput } from "../input/input";
import { Icon } from "../icons/icons";
import { CoreText, CoreTextType } from "../text/text";
import { getFormBuilderComponents } from "./forms/form_builder_components";
export interface IFormBuilder {
formBuilder: FormBuilderValidationModel;
@ -33,7 +34,7 @@ export const FormBuilder = observer((props: IFormBuilder) => {
return (
<div>
{store.isError ? (
{store.isError ? (
<>Error</>
) : (
<div>
@ -51,7 +52,6 @@ export const FormBuilder = observer((props: IFormBuilder) => {
);
}
if (element.type.isEqual(InputType.ARRAY)) {
return (
<div style={{ border: "1px black solid", margin: 20 }}>
<div
@ -146,7 +146,26 @@ export const FormBuilder = observer((props: IFormBuilder) => {
/>
</div>
);
if (element.type.isEqual(InputType.OBJECT))
return (
<>
{getFormBuilderComponents(
element.name.replace(">", "").replace("<", "").replace("/", ""),
element.totalValue ?? element.defaultValue,
(text) => {
store.changeTotalValue(element.id, text);
}
).fold(
(s) => (
<>{s}</>
),
(error) => (
<>{error}</>
)
)}
</>
);
return <>Error</>;
})}
</div>

View file

@ -44,13 +44,17 @@ export class FormBuilderStore {
}
}
changeTotalValue(id: string, value: string) {
changeTotalValue(id: string, value: any) {
if (this.formViewModel?.inputs)
this.formViewModel.inputs = this.formViewModel?.inputs.map((el) => {
if (!el.id.isEqual(id)) {
return el;
}
el.totalValue = value;
if (value instanceof String) {
el.totalValue = value;
}else{
el.totalValue = JSON.stringify(value)
}
return el;
});
this.changerForm.emit(this.formViewModel?.fromFormBuilderValidationModel());

View file

@ -8,6 +8,7 @@ export enum InputType {
STRING = "string",
ARRAY = "Array",
ENUM = "Enum",
OBJECT = "OBJECT",
}
interface IOperation {
@ -29,6 +30,11 @@ export class InputBuilderViewModel {
) {
this.id = id ?? uuidv4();
}
isReactComponent = () => {
if (this.name.match(new RegExp(/<.*>/gm)) === null) {
throw new Error("Is dont react component" + this);
}
};
static fromJSON(json: any) {
try {
const value = JSON.parse(json);
@ -58,7 +64,8 @@ export class InputBuilderViewModel {
}
}
export const tagParse = new RegExp(/\${.*?}/gm);
export const tagParse = new RegExp(/\${.*?.*}/g);
export const objectParse = new RegExp(/OBJECT:.*}/gm);
export const bracketParser = new RegExp(/<.*?>/gm);
export const enumParser = new RegExp(/ENUM.*=..*?;/gm);
export const enumBodyParse = new RegExp(/".*?;/gm);
@ -66,7 +73,8 @@ export const enumNameParse = new RegExp(/^(.*?)=/gm);
export const typeBodyParse = new RegExp(/{.*?};/gms);
export const typeNameParse = new RegExp(/type .*?{/gms);
export const typeParse = new RegExp(/type.*?};/gms);
export const objectParseObj = new RegExp(/{.*}/gm);
export const multiTagParse = new RegExp(/\${.*?}/g);
export class FormViewModel {
@observable
inputs: InputBuilderViewModel[];
@ -106,6 +114,9 @@ export class FormViewModel {
if (element.type.isEqual(InputType.NUMBER)) {
inputResult = Number(inputResult);
}
if (element.type.isEqual(InputType.OBJECT)) {
inputResult = JSON.stringify(element.totalValue ?? element.defaultValue);
}
if (element.type.isEqual(InputType.ARRAY)) {
if (element.totalValue === undefined) {
inputResult = "[]";
@ -171,6 +182,9 @@ export class FormViewModel {
}
static fromString(result: string, context: string): Result<void, FormViewModel> {
try {
if(result.isEmpty() && context.isEmpty()){
return Result.error(undefined)
}
const enums = new Map<string, string[]>();
const types = new Map<string, InputBuilderViewModel[]>();
@ -205,37 +219,60 @@ export class FormViewModel {
return result
.match(tagParse)
?.map((el) => {
const inputArray = el.replaceMany(["$", "{", "}"], "").split(":");
if (el.includes(InputType.ENUM)) {
const enumName = inputArray.at(1)?.replaceMany([InputType.ENUM, "<", ">"], "");
if (enumName && enums.get(enumName)) {
return new InputBuilderViewModel(inputArray[0], InputType.ENUM, inputArray[2], enums.get(enumName));
}
const multiTag = el.match(multiTagParse);
const result = [];
if (multiTag?.length !== 0 && multiTag?.length !== 1) {
multiTag?.forEach((element) => {
result.push(this.tagParse(element, enums, types));
});
} else {
result.push(this.tagParse(el, enums, types));
}
if (el.includes(InputType.ARRAY) && types) {
const name = inputArray.at(1)?.replaceMany(["Array<", ">"], "");
if (name) {
return new InputBuilderViewModel(
inputArray[0],
InputType.ARRAY,
inputArray[2],
types.get(name),
undefined,
false,
name
);
}
}
if (el.includes(InputType.NUMBER)) {
return new InputBuilderViewModel(inputArray[0], InputType.NUMBER, inputArray[2]);
}
if (el.includes(InputType.STRING)) {
return new InputBuilderViewModel(inputArray[0], InputType.STRING, inputArray[2]);
}
return el;
return result;
})
.flat()
.filter((el) => el !== undefined) as InputBuilderViewModel[];
}
public static tagParse = (
el: string,
enums: Map<string, string[]>,
types: Map<string, InputBuilderViewModel[]> | undefined = undefined
) => {
const inputArray = el.replaceMany(["$", "{", "}"], "").split(":");
if (el.includes(InputType.ENUM)) {
const enumName = inputArray.at(1)?.replaceMany([InputType.ENUM, "<", ">"], "");
if (enumName && enums.get(enumName)) {
return new InputBuilderViewModel(inputArray[0], InputType.ENUM, inputArray[2], enums.get(enumName));
}
}
if (el.includes(InputType.ARRAY) && types) {
const name = inputArray.at(1)?.replaceMany(["Array<", ">"], "");
if (name) {
return new InputBuilderViewModel(
inputArray[0],
InputType.ARRAY,
inputArray[2],
types.get(name),
undefined,
false,
name
);
}
}
if (el.includes(InputType.OBJECT)) {
const objectParseResult = el.match(objectParse)?.at(0);
const result = objectParseResult?.slice(objectParseResult?.indexOf(":") + 1, objectParseResult.length) as string;
return new InputBuilderViewModel(inputArray[0], InputType.OBJECT, JSON.parse(result));
}
if (el.includes(InputType.NUMBER)) {
return new InputBuilderViewModel(inputArray[0], InputType.NUMBER, inputArray[2]);
}
if (el.includes(InputType.STRING)) {
return new InputBuilderViewModel(inputArray[0], InputType.STRING, inputArray[2]);
}
return el;
};
}

View file

@ -0,0 +1,20 @@
import { Result } from "../../../helper/result";
import { SelectScene } from "./select_scene/select_scene";
export enum FormBuilderComponents {
SelectScene = "SelectScene",
}
export interface IFormBuilderComponentsProps<T> {
dependency: T;
onChange: (obj: any) => void;
}
export const getFormBuilderComponents = (
name: string,
dependency: any,
onChange: (text: string) => void
): Result<string, React.ReactNode> => {
if (name.isEqual(FormBuilderComponents.SelectScene)) {
return Result.ok(<SelectScene dependency={dependency} onChange={onChange}/>);
}
return Result.error(name);
};

View file

@ -0,0 +1,22 @@
import { CoreButton } from "../../../button/button";
import { IFormBuilderComponentsProps } from "../form_builder_components";
export class SceneSelectModel {
name: string;
}
export const SelectScene = (props: IFormBuilderComponentsProps<SceneSelectModel>) => {
return (
<div>
SELECT SCENE
<div>
{JSON.stringify(props.dependency)}
</div>
<CoreButton
text="CHANGE"
onClick={() => {
props.dependency.name = '15555'
props.onChange(JSON.stringify(props.dependency, () => {}, ""));
}}
/>
</div>
);
};

View file

@ -4,6 +4,7 @@ import { IStyle } from "../../model/style";
export enum CoreInputType {
small = "small",
default = "default",
big = 'big'
}
interface IInputProps extends IStyle {
label: string;
@ -32,7 +33,7 @@ export const CoreInput = (props: IInputProps) => {
{
backgroundColor: "rgba(230, 224, 233, 1)",
height: isSmall ? 40 : 58,
height: isSmall ? 40 : 58,
borderRadius: "4px 4px 0px 0px",
borderBottom: "solid 1px black",
padding: "10px 10px 10px 10px",
@ -44,6 +45,7 @@ export const CoreInput = (props: IInputProps) => {
<CoreText type={CoreTextType.small} style={isSmall ? { fontSize: 8, position:'relative',top:-8 } : {}} text={props.label} />
<input
size={100}
defaultValue={props.value}
style={{
backgroundColor: "#00008000",

View file

@ -9,7 +9,7 @@ import { AssemblesScreenPath } from "../../../features/assembles/assembles_scree
import { SimulationScreenPath } from "../../../features/simulations/simulations_screen";
import { EstimateScreenPath } from "../../../features/estimate/estimate_screen";
import { BehaviorTreeBuilderPath } from "../../../features/behavior_tree_builder/presentation/behavior_tree_builder_screen";
import { SkillPath as SkillScreenPath } from "../../../features/skils/skills_screen";
import { MachineLearningPath as SkillScreenPath } from "../../../features/machine_learning/presentation/machine_learning_screen";
import { UiBaseError } from "../../model/ui_base_error";
import { DetailsScreenPath } from "../../../features/details/details_screen";
export interface IBlockProps {

View file

@ -11,6 +11,7 @@ interface ICoreSelectProps extends IStyle {
export const CoreSelect = (props: ICoreSelectProps) => {
const ref = React.useRef<HTMLDivElement>(null);
const [cursorIsCorses, setCursorIsCorses] = React.useState(false);
const [width, setWidth] = React.useState(0);
const [value, setValue] = React.useState(props.value);
React.useEffect(() => {
ref.current?.addEventListener("mousemove", () => {
@ -19,6 +20,8 @@ export const CoreSelect = (props: ICoreSelectProps) => {
ref.current?.addEventListener("mouseleave", () => {
setCursorIsCorses(false);
});
setWidth(Number(ref.current?.clientWidth));
}, [ref, setCursorIsCorses]);
return (
@ -42,26 +45,30 @@ export const CoreSelect = (props: ICoreSelectProps) => {
borderRadius: 4,
}}
>
{cursorIsCorses
? props.items.map((el, i) => (
<div
key={i}
onClick={() => {
setValue(el);
props.onChange(el);
}}
style={{
height: 48,
textAlign: "center",
alignContent: "center",
cursor: "pointer",
borderBottom: "1px solid",
}}
>
{el}
</div>
))
: null}
<div style={{ position: "absolute", width: width, backgroundColor: "rgba(230, 224, 233, 1)" }}>
{cursorIsCorses
? props.items.map((el, i) => (
<div
key={i}
onClick={() => {
setValue(el);
props.onChange(el);
}}
style={{
backgroundColor: "rgba(230, 224, 233, 1)",
width: width,
height: 48,
textAlign: "center",
alignContent: "center",
cursor: "pointer",
borderBottom: "1px solid",
}}
>
{el}
</div>
))
: null}
</div>
</div>
</div>
);

View file

@ -171,7 +171,7 @@ export class BehaviorTreeBuilderStore extends UiDrawerFormState<BehaviorTreeView
if (keyCode === 16) {
this.shiftIsPressed = false;
}
if (keyCode === 8) {
if (keyCode === 8 || keyCode === 46) {
this.deleteIsPressed = false;
}
});

View file

@ -1,7 +1,7 @@
import makeAutoObservable from "mobx-store-inheritance";
import { FormState, CoreError } from "../../../../../../core/store/base_store";
import { DataSetHttpRepository } from "../../../../../dataset/dataset_http_repository";
import { ISkils, SkillsHttpRepository } from "../../../../../skils/skills_http_repository";
import { ISkils, SkillsHttpRepository } from "../../../../../machine_learning/data/machine_learning_http_repository";
import { WeightsViewModel } from "./weights_view_model";
import { Parts } from "../../../../../details/details_http_repository";

View file

@ -6,7 +6,7 @@ export enum ProcessStatus {
ERROR = "ERROR",
NEW = "NEW",
RUN = "RUN",
NONE = "none"
NONE = "none",
}
export interface IDatasetModel {
@ -31,7 +31,6 @@ export interface Dataset {
formBuilder: FormBuilderValidationModel;
}
export interface Asset {
name: string;
mesh: string;
@ -48,16 +47,30 @@ export class FormBuilderValidationModel {
this.form = form;
this.output = output;
}
static empty() {
static datasetEmpty() {
return new FormBuilderValidationModel(datasetFormMockContext, datasetFormMockResult, [], defaultFormValue);
}
static empty() {
return new FormBuilderValidationModel("", "", [], "");
}
static emptyTest() {
return new FormBuilderValidationModel(
`
`,
``,
[],
defaultFormValue
);
}
}
export class DataSetModel {
dataSetObjects: string[];
datasetType: string;
name: string;
formBuilder: FormBuilderValidationModel = FormBuilderValidationModel.empty();
formBuilder: FormBuilderValidationModel = FormBuilderValidationModel.datasetEmpty();
project?: string;
processStatus?: string;
isNew: boolean;
@ -103,8 +116,10 @@ export class DataSetModel {
export const datasetTypes = ["Object Detection - YOLOv8", "Pose Estimation - DOPE"];
export const datasetFormMockResult = `{
"typedataset": \${typedataset:Enum<T>:ObjectDetection},
"scene":\${<SelectScene/>:OBJECT:{"bricks":{"base_feature":{"path":"bricks/base_feature"},"form":{"path":"bricks/form"}}},
"models_randomization":{
"loc_range_low": [\${LOC_RANGE_LOW_1:number:-1}, \${LOC_RANGE_LOW_2:number:-1},/\${LOC_RANGE_LOW_3:number:0}],
"loc_range_high": [\${LOC_RANGE_HIGH_1:number:1}, \${LOC_RANGE_HIGH_2:number:1},/\${LOC_RANGE_HIGH_3:number:2}]

View file

@ -1,7 +1,7 @@
import { Result } from "../../core/helper/result";
import { HttpError, HttpMethod, CoreHttpRepository } from "../../core/repository/http_repository";
import { IDatasetModel } from "../dataset/dataset_model";
import { SkillModel } from "./skill_model";
import { Result } from "../../../core/helper/result";
import { HttpError, HttpMethod, CoreHttpRepository } from "../../../core/repository/http_repository";
import { IDatasetModel } from "../../dataset/dataset_model";
import { Model } from "../model/model_machine_learning_process";
export interface ISkils {
_id: string;
@ -29,7 +29,7 @@ export class SkillsHttpRepository extends CoreHttpRepository {
return this._jsonRequest<void>(HttpMethod.DELETE, `/weights?id=${id}`);
};
addNewSkill = async (model: SkillModel) => {
addNewSkill = async (model: Model) => {
return this._jsonRequest(HttpMethod.POST, "/weights", model);
};
getDatasetsActiveProject = async (): Promise<Result<HttpError, IDatasetModel[]>> => {

View file

@ -1,6 +1,6 @@
import { TypedEvent } from "../../core/helper/typed_event";
import { SocketRepository, socketRepository } from "../../core/repository/socket_repository";
import { ProcessStatus } from "../dataset/dataset_model";
import { TypedEvent } from "../../../core/helper/typed_event";
import { SocketRepository, socketRepository } from "../../../core/repository/socket_repository";
import { ProcessStatus } from "../../dataset/dataset_model";
export interface ProcessUpdate {
id: string;

View file

@ -0,0 +1,87 @@
import makeAutoObservable from "mobx-store-inheritance";
import { Result } from "../../../core/helper/result";
import { ISkils } from "../data/machine_learning_http_repository";
import { FormBuilderValidationModel } from "../../dataset/dataset_model";
import { IsString } from "class-validator";
import { ValidationModel } from "../../../core/model/validation_model";
export enum ModelMachineLearningTypes {
OBJECT_DETECTION = "OBJECT_DETECTION",
POSE_ESTIMATE = "POSE_ESTIMATE",
ML = "ML",
}
export class ModelMachineLearningProcess extends ValidationModel {
@IsString()
script: string;
formBuilder: FormBuilderValidationModel;
@IsString()
type: string;
@IsString()
name: string;
isEnd: boolean = false;
createDate: Date = new Date();
card?: string;
lastProcessLogs?: string;
lastProcessExecCommand?: string;
lastExecDate?: Date;
constructor(script: string, formBuilderValidationModel: FormBuilderValidationModel, type: string, card: string) {
super();
this.script = script;
this.formBuilder = formBuilderValidationModel;
this.type = type;
this.card = card;
}
static empty = () => new ModelMachineLearningProcess("", FormBuilderValidationModel.empty(), "", "");
}
export class Model {
numberOfTrainedEpochs?: number;
id?: string;
isFinished?: boolean;
constructor(
public name: string,
public datasetId: string,
public project: string,
public epoch: number,
numberOfTrainedEpochs?: number,
id?: string,
isFinished?: boolean
) {
this.numberOfTrainedEpochs = numberOfTrainedEpochs;
this.id = id;
this.isFinished = isFinished;
makeAutoObservable(this);
}
static fromISkill(model: ISkils) {
return new Model(
model.name,
model.datasetId._id,
model.project._id,
model.epoch,
model.numberOfTrainedEpochs,
model._id,
model.isFinished
);
}
static empty() {
return new Model("", "", "", 0);
}
valid(): Result<string, Model> {
if (this.name.isEmpty()) {
return Result.error("введите имя скила");
}
if (this.datasetId.isEmpty()) {
return Result.error("datasetId is empty");
}
if (this.project.isEmpty()) {
return Result.error("project is empty");
}
if (this.epoch.isNegative()) {
return Result.error("эпоха не может принимать отрицательное число");
}
return Result.ok(this);
}
}

View file

@ -1,13 +1,16 @@
import React from "react";
import { Drawer } from "antd";
import { Alert, Drawer, Modal } from "antd";
import { observer } from "mobx-react-lite";
import { MainPage } from "../../core/ui/pages/main_page";
import { CoreText, CoreTextType } from "../../core/ui/text/text";
import { DrawersSkill, SkillStore } from "./skills_store";
import { SkillCard } from "./skill_card";
import { CoreInput } from "../../core/ui/input/input";
import { CoreButton } from "../../core/ui/button/button";
import { CoreSwitch } from "../../core/ui/switch/switch";
import { MainPage } from "../../../core/ui/pages/main_page";
import { CoreText, CoreTextType } from "../../../core/ui/text/text";
import { DrawersSkill, MachineLearningStore } from "./machine_learning_store";
import { ModelCard } from "./ui/cards/pose_estimate_card/model_card";
import { CoreInput, CoreInputType } from "../../../core/ui/input/input";
import { CoreButton } from "../../../core/ui/button/button";
import { CoreSelect } from "../../../core/ui/select/select";
import { ModelMachineLearningTypes } from "../model/model_machine_learning_process";
import { CardModel } from "./ui/cards/get_model_card";
import { FormBuilder } from "../../../core/ui/form_builder/form_builder";
interface IItem {
name: string;
@ -16,10 +19,10 @@ interface IItem {
const skills: IItem[] = [{ name: "ML", isActive: true }];
export const SkillPath = "/skills";
export const MachineLearningPath = "/models";
export const SkillScreen = observer(() => {
const [store] = React.useState(() => new SkillStore());
export const MachineLearningScreen = observer(() => {
const [store] = React.useState(() => new MachineLearningStore());
React.useEffect(() => {
store.init();
@ -48,7 +51,7 @@ export const SkillScreen = observer(() => {
}}
>
{store.skils?.map((el) => (
<SkillCard
<ModelCard
datasetName={el.datasetId.name}
id={el._id}
isFinished={el.isFinished}
@ -63,7 +66,7 @@ export const SkillScreen = observer(() => {
onDelete={(id) => store.deleteSkill(id)}
/>
))}
<SkillCard empty={true} emptyOnClick={() => store.editDrawer(DrawersSkill.NEW_SKILL, true)} />
<ModelCard empty={true} emptyOnClick={() => store.editDrawer(DrawersSkill.NEW_SKILL, true)} />
</div>
}
/>
@ -74,23 +77,6 @@ export const SkillScreen = observer(() => {
open={store.drawers.find((el) => el.name === DrawersSkill.EDIT_SKILL)?.status}
>
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}>
<div>
<CoreInput
value={(store.viewModel.epoch ?? "").toString()}
label={"добавить эпох"}
validation={(value) => Number().isValid(value)}
error="Должно быть введено число"
onChange={(text) => store.updateForm({ epoch: Number(text) })}
/>
<div style={{ display: "flex", alignItems: "center",margin:10 }}>
<CoreText text={"Завершен?"} type={CoreTextType.header} /> <div style={{ width: 10 }} />
<CoreSwitch
id={store.viewModel.id ?? ""}
isSelected={store.viewModel.isFinished ?? false}
onChange={() => store.updateForm({isFinished: !store.viewModel.isFinished})}
/>
</div>
</div>
<div style={{ display: "flex" }}>
<CoreButton text="Сохранить" filled={true} onClick={() => store.saveEdiSkill()} />
<div style={{ width: 10 }} />
@ -99,46 +85,49 @@ export const SkillScreen = observer(() => {
</div>
</Drawer>
<Drawer
width={(window.innerWidth / 100) * 50}
title={store.titleDrawer}
destroyOnClose={true}
onClose={() => store.editDrawer(DrawersSkill.NEW_SKILL, false)}
open={store.drawers.find((el) => el.name === DrawersSkill.NEW_SKILL)?.status}
>
<div style={{ display: "flex", flexDirection: "column", justifyContent: "space-between", height: "100%" }}>
<CoreInput
value={store.viewModel.name}
label={"Имя навыка"}
onChange={(text) => store.updateForm({ name: text })}
/>
<CoreInput
value={store.viewModel.epoch.toString()}
label="Количество эпох"
onChange={(e) => store.updateForm({ epoch: Number(e) })}
/>
<div style={{ height: "100%" }}>
{store.datasets?.map((el) => (
<div
style={{
border: "1px solid rgb(103, 80, 164)",
backgroundColor: "rgb(254, 247, 255)",
borderRadius: 12,
margin: 10,
padding: 10,
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
{el.name}
<CoreSwitch
isSelected={store.viewModel.datasetId.isEqual(el._id)}
id={el._id}
onChange={() => store.updateForm({ datasetId: el._id })}
/>
</div>
))}
<div>
<CoreSelect
items={Object.keys(ModelMachineLearningTypes)}
value={store.viewModel.type}
label={"Тип навыка"}
onChange={(text: string) => store.updateForm({ type: text })}
/>
<CoreSelect
items={Object.keys(CardModel)}
value={""}
label={"Тип карточки"}
onChange={(text: string) => store.updateForm({ card: text })}
/>
<CoreInput label="Имя" onChange={(text) => store.updateForm({ name: text })} />
<CoreInput label="Команда для запуска" />
<CoreInput
label="FormBuilder Result"
onChange={(text) => {
store.viewModel.formBuilder.result = text;
}}
style={{ height: 200 }}
/>
<CoreInput
label="FormBuilder Context"
onChange={(text) => {
store.viewModel.formBuilder.context = text;
}}
style={{ height: 200 }}
/>
<CoreButton
text={"Посмотреть form builder "}
onClick={() => {
store.isModalOpen = true;
}}
/>
</div>
<div style={{ display: "flex" }}>
<CoreButton text="Сохранить" filled={true} onClick={() => store.saveSkill()} />
<div style={{ width: 10 }} />
@ -146,6 +135,19 @@ export const SkillScreen = observer(() => {
</div>
</div>
</Drawer>
<Modal
destroyOnClose={true}
open={store.isModalOpen}
footer={null}
closable={false}
closeIcon={null}
onCancel={() => {
store.isModalOpen = false;
}}
>
<FormBuilder formBuilder={store.viewModel.formBuilder} onChange={() => {}} />
</Modal>
<Alert />
</>
);
});

View file

@ -1,29 +1,29 @@
import makeAutoObservable from "mobx-store-inheritance";
import { NavigateFunction } from "react-router-dom";
import { HttpError } from "../../core/repository/http_repository";
import { Drawer, UiDrawerFormState } from "../../core/store/base_store";
import { ISkils, SkillsHttpRepository } from "./skills_http_repository";
import { IDatasetModel } from "../dataset/dataset_model";
import { HttpError } from "../../../core/repository/http_repository";
import { Drawer, UiDrawerFormState } from "../../../core/store/base_store";
import { ISkils, SkillsHttpRepository } from "../data/machine_learning_http_repository";
import { IDatasetModel } from "../../dataset/dataset_model";
import { message } from "antd";
import { UUID } from "../all_projects/data/project_http_repository";
import { SkillModel } from "./skill_model";
import { ProcessUpdate, SkillSocketRepository } from "./skill_socket_repository";
import { UUID } from "../../all_projects/data/project_http_repository";
import { Model, ModelMachineLearningProcess } from "../model/model_machine_learning_process";
import { ProcessUpdate, SkillSocketRepository } from "../data/machine_learning_socket_repository";
export enum DrawersSkill {
NEW_SKILL = "Новый навык",
EDIT_SKILL = "Редактировать навык",
}
export class SkillStore extends UiDrawerFormState<SkillModel, HttpError> {
export class MachineLearningStore extends UiDrawerFormState<ModelMachineLearningProcess, HttpError> {
skillsHttpRepository: SkillsHttpRepository;
skillSocketRepository: SkillSocketRepository = new SkillSocketRepository();
skils?: ISkils[];
datasets?: IDatasetModel[];
activeProjectId?: UUID;
viewModel: SkillModel;
viewModel: ModelMachineLearningProcess;
titleDrawer: string = DrawersSkill.NEW_SKILL;
drawers: Drawer[];
isModalOpen:boolean = false;
constructor() {
super({});
this.drawers = Object.entries(DrawersSkill).map((k, v) => {
@ -32,7 +32,7 @@ export class SkillStore extends UiDrawerFormState<SkillModel, HttpError> {
status: false,
};
});
this.viewModel = SkillModel.empty();
this.viewModel = ModelMachineLearningProcess.empty();
this.skillsHttpRepository = new SkillsHttpRepository();
this.skillSocketRepository.on(this.socketUpdate);
makeAutoObservable(this);
@ -75,22 +75,29 @@ export class SkillStore extends UiDrawerFormState<SkillModel, HttpError> {
await this.mapOk("datasets", this.skillsHttpRepository.getDatasetsActiveProject());
await this.mapOk("activeProjectId", this.skillsHttpRepository.getActiveProjectId());
};
saveSkill() {
this.viewModel.project = this.activeProjectId?.id ?? "";
this.viewModel.valid().fold(
async (model) => {
(await this.skillsHttpRepository.addNewSkill(model)).fold(
async (s) => {
message.success("Новый ");
this.viewModel = SkillModel.empty();
await this.mapOk("skils", this.skillsHttpRepository.getAllSkills());
},
async (e) => message.error(e.message)
);
saveSkill = async () =>
(await this.viewModel.valid()).fold(
async (s) => {
message.success("URA")
},
async (e) => message.error(e)
async (e) => {
message.error(e);
}
);
}
// this.viewModel.project = this.activeProjectId?.id ?? "";
// this.viewModel.valid().fold(
// async (model) => {
// (await this.skillsHttpRepository.addNewSkill(model)).fold(
// async (s) => {
// message.success("Новый ");
// this.viewModel = Model.empty();
// await this.mapOk("skils", this.skillsHttpRepository.getAllSkills());
// },
// async (e) => message.error(e.message)
// );
// },
// async (e) => message.error(e)
// );
editDrawer(drawerName: DrawersSkill, status: boolean): void {
this.titleDrawer = drawerName;
@ -106,15 +113,15 @@ export class SkillStore extends UiDrawerFormState<SkillModel, HttpError> {
await this.init();
};
fromEditSkill(id: string): void {
this.viewModel = SkillModel.fromISkill(this.getSkillById(id) as ISkils);
// this.viewModel = Model.fromISkill(this.getSkillById(id) as ISkils);
this.editDrawer(DrawersSkill.EDIT_SKILL, true);
}
saveEdiSkill = async () => {
const skillOrigin = this.getSkillById(this.viewModel.id as string) as ISkils;
skillOrigin.numberOfTrainedEpochs = this.viewModel.epoch;
skillOrigin.isFinished = this.viewModel.isFinished ?? false;
await this.skillsHttpRepository.editSkill(skillOrigin);
// const skillOrigin = this.getSkillById(this.viewModel.id as string) as ISkils;
// skillOrigin.numberOfTrainedEpochs = this.viewModel.epoch;
// skillOrigin.isFinished = this.viewModel.isFinished ?? false;
// await this.skillsHttpRepository.editSkill(skillOrigin);
this.editDrawer(DrawersSkill.EDIT_SKILL, false);
};
}

View file

@ -0,0 +1,4 @@
export enum CardModel {
pose_estimate = "pose_estimate",
}
export const getModelCard = () => {};

View file

@ -1,13 +1,13 @@
import { CoreButton } from "../../core/ui/button/button";
import { Icon } from "../../core/ui/icons/icons";
import { CoreButton } from "../../../../../../core/ui/button/button";
import { Icon } from "../../../../../../core/ui/icons/icons";
import { Dropdown } from "antd";
import { CoreText, CoreTextType } from "../../core/ui/text/text";
import { ProcessStatus } from "../dataset/dataset_model";
import { IMenuItem } from "../dataset/card_dataset";
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 {
export interface IModelCardProps {
processStatus?: string;
name?: string;
isFinished?: boolean;
@ -23,7 +23,7 @@ export interface ISkillCardProps {
epochNextTraining?: number;
}
export const SkillCard = (props: ISkillCardProps) => {
export const ModelCard = (props: IModelCardProps) => {
const menu: IMenuItem[] = [
{
onClick: () => {

View file

@ -51,7 +51,7 @@ export const CameraForm = observer((props: IDefaultSceneManagerFormProps) => {
/>
<CoreInput
value={String(store.viewModel.near)}
label={"Far"}
label={"Near"}
validation={(text) => Number().isValid(text)}
onChange={(text) => (store.updateForm({ near: Number(text) }), store.updateCameraScene())}
/>

View file

@ -96,7 +96,10 @@ export class SceneMangerStore extends UiDrawerFormState<SceneViewModel, HttpErro
this.sceneHttpRepository = new SceneHttpRepository();
this.sceneMode = SceneMode.Select;
}
sceneSave = () => this.sceneHttpRepository.editScene(SceneAsset.newScene(this.scene, this.sceneName ?? ""));
sceneSave = () =>
this.messageHttp(this.sceneHttpRepository.editScene(SceneAsset.newScene(this.scene, this.sceneName ?? "")), {
successMessage: "Сцена сохранена",
}).then(() => (this.isVisibleSaveButton = false));
iconToSceneManagerForm = (icon: string): SceneManagerForms => {
if (icon.isEqual("Camera")) {

View file

@ -1,55 +0,0 @@
import makeAutoObservable from "mobx-store-inheritance";
import { Result } from "../../core/helper/result";
import { ISkils } from "./skills_http_repository";
export class SkillModel {
numberOfTrainedEpochs?: number;
id?: string;
isFinished?:boolean;
constructor(
public name: string,
public datasetId: string,
public project: string,
public epoch: number,
numberOfTrainedEpochs?: number,
id?: string,
isFinished?:boolean
) {
this.numberOfTrainedEpochs = numberOfTrainedEpochs;
this.id = id;
this.isFinished = isFinished
makeAutoObservable(this);
}
static fromISkill(model: ISkils) {
return new SkillModel(
model.name,
model.datasetId._id,
model.project._id,
model.epoch,
model.numberOfTrainedEpochs,
model._id,
model.isFinished
);
}
static empty() {
return new SkillModel("", "", "", 0);
}
valid(): Result<string, SkillModel> {
if (this.name.isEmpty()) {
return Result.error("введите имя скила");
}
if (this.datasetId.isEmpty()) {
return Result.error("datasetId is empty");
}
if (this.project.isEmpty()) {
return Result.error("project is empty");
}
if (this.epoch.isNegative()) {
return Result.error("эпоха не может принимать отрицательное число");
}
return Result.ok(this);
}
}

View file

@ -6,6 +6,7 @@ import { SocketLister } from "./features/socket_lister/socket_lister";
import { RouterProvider } from "react-router-dom";
import { router } from "./core/routers/routers";
import { configure } from "mobx";
configure({
enforceActions: "never",