progress machine learning screen
This commit is contained in:
parent
0b3eefec2d
commit
d41310196f
24 changed files with 428 additions and 231 deletions
22
ui/src/core/model/validation_model.ts
Normal file
22
ui/src/core/model/validation_model.ts
Normal 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);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -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 />,
|
||||
},
|
||||
]);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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",
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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}]
|
||||
|
|
|
@ -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[]>> => {
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 />
|
||||
</>
|
||||
);
|
||||
});
|
|
@ -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);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export enum CardModel {
|
||||
pose_estimate = "pose_estimate",
|
||||
}
|
||||
export const getModelCard = () => {};
|
|
@ -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: () => {
|
|
@ -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())}
|
||||
/>
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue