chore: improve the result in classification closes #34
This commit is contained in:
parent
3f828ab855
commit
f8bc8ad85a
@ -8,12 +8,32 @@ import (
|
||||
)
|
||||
|
||||
func handleList(handler *Handle) {
|
||||
|
||||
handler.PostAuth("/tasks/task", 1, func(c *Context) *Error {
|
||||
var getId JustId
|
||||
if _err := c.ToJSON(&getId); _err != nil {
|
||||
return _err
|
||||
}
|
||||
|
||||
var task Task
|
||||
|
||||
err := GetDBOnce(c, &task, "tasks where id=$1;", getId.Id)
|
||||
if err == NotFoundError {
|
||||
return c.JsonBadRequest("Did not found task id")
|
||||
} else if err != nil {
|
||||
return c.E500M("Faied to get task", err)
|
||||
}
|
||||
|
||||
c.ShowMessage = false
|
||||
return c.SendJSON(task)
|
||||
})
|
||||
|
||||
handler.PostAuth("/tasks/list", 1, func(c *Context) *Error {
|
||||
var err error = nil
|
||||
var err error = nil
|
||||
|
||||
var requestData struct {
|
||||
ModelId string `json:"model_id"`
|
||||
Page int `json:"page"`
|
||||
Page int `json:"page"`
|
||||
}
|
||||
|
||||
if _err := c.ToJSON(&requestData); _err != nil {
|
||||
@ -33,29 +53,29 @@ func handleList(handler *Handle) {
|
||||
}
|
||||
}
|
||||
|
||||
var rows []*Task = nil
|
||||
var rows []*Task = nil
|
||||
|
||||
if requestData.ModelId != "" {
|
||||
rows, err = GetDbMultitple[Task](c, "tasks where model_id=$1 order by created_on desc limit 11 offset $2", requestData.ModelId, requestData.Page * 10)
|
||||
rows, err = GetDbMultitple[Task](c, "tasks where model_id=$1 order by created_on desc limit 11 offset $2", requestData.ModelId, requestData.Page*10)
|
||||
if err != nil {
|
||||
return c.Error500(err)
|
||||
}
|
||||
} else {
|
||||
rows, err = GetDbMultitple[Task](c, "tasks order by created_on desc limit 11 offset $1", requestData.Page * 10)
|
||||
rows, err = GetDbMultitple[Task](c, "tasks order by created_on desc limit 11 offset $1", requestData.Page*10)
|
||||
if err != nil {
|
||||
return c.Error500(err)
|
||||
}
|
||||
}
|
||||
|
||||
max_len := min(11, len(rows))
|
||||
|
||||
c.ShowMessage = false
|
||||
|
||||
c.ShowMessage = false
|
||||
return c.SendJSON(struct {
|
||||
TaskList []*Task `json:"task_list"`
|
||||
ShowNext bool `json:"show_next"`
|
||||
} {
|
||||
rows[0:max_len],
|
||||
len(rows) > 10,
|
||||
})
|
||||
TaskList []*Task `json:"task_list"`
|
||||
ShowNext bool `json:"show_next"`
|
||||
}{
|
||||
rows[0:max_len],
|
||||
len(rows) > 10,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
12
main.go
12
main.go
@ -8,10 +8,10 @@ import (
|
||||
_ "github.com/lib/pq"
|
||||
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks"
|
||||
models_utils "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks/runner"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -35,10 +35,10 @@ func main() {
|
||||
defer db.Close()
|
||||
log.Info("Starting server on :5002!")
|
||||
|
||||
config := LoadConfig()
|
||||
log.Info("Config loaded!", "config", config)
|
||||
config := LoadConfig()
|
||||
log.Info("Config loaded!", "config", config)
|
||||
|
||||
StartRunners(db, config)
|
||||
StartRunners(db, config)
|
||||
|
||||
//TODO check if file structure exists to save data
|
||||
handle := NewHandler(db, config)
|
||||
@ -59,7 +59,7 @@ func main() {
|
||||
|
||||
usersEndpints(db, handle)
|
||||
HandleModels(handle)
|
||||
HandleTasks(handle)
|
||||
HandleTasks(handle)
|
||||
|
||||
handle.Startup()
|
||||
}
|
||||
|
34
webpage/src/lib/Spinner.svelte
Normal file
34
webpage/src/lib/Spinner.svelte
Normal file
@ -0,0 +1,34 @@
|
||||
<svg width="24" height="24" stroke="#000" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.spinner_V8m1 {
|
||||
transform-origin: center;
|
||||
animation: spinner_zKoa 2s linear infinite;
|
||||
}
|
||||
.spinner_V8m1 circle {
|
||||
stroke-linecap: round;
|
||||
animation: spinner_YpZS 1.5s ease-in-out infinite;
|
||||
}
|
||||
@keyframes spinner_zKoa {
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes spinner_YpZS {
|
||||
0% {
|
||||
stroke-dasharray: 0 150;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
47.5% {
|
||||
stroke-dasharray: 42 150;
|
||||
stroke-dashoffset: -16;
|
||||
}
|
||||
95%,
|
||||
100% {
|
||||
stroke-dasharray: 42 150;
|
||||
stroke-dashoffset: -59;
|
||||
}
|
||||
}
|
||||
</style><g class="spinner_V8m1"
|
||||
><circle cx="12" cy="12" r="9.5" fill="none" stroke-width="3"></circle></g
|
||||
>
|
||||
</svg>
|
After Width: | Height: | Size: 767 B |
@ -1,95 +1,111 @@
|
||||
<script lang="ts">
|
||||
import { postFormData } from "src/lib/requests.svelte";
|
||||
import type { Model } from "./+page.svelte";
|
||||
import FileUpload from "src/lib/FileUpload.svelte";
|
||||
import MessageSimple from "src/lib/MessageSimple.svelte";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { post, postFormData } from 'src/lib/requests.svelte';
|
||||
import type { Model } from './+page.svelte';
|
||||
import FileUpload from 'src/lib/FileUpload.svelte';
|
||||
import MessageSimple from 'src/lib/MessageSimple.svelte';
|
||||
import { createEventDispatcher, onDestroy } from 'svelte';
|
||||
import Spinner from 'src/lib/Spinner.svelte';
|
||||
import type { Task } from './TasksTable.svelte';
|
||||
|
||||
let {model} = $props<{model: Model}>();
|
||||
let { model } = $props<{ model: Model }>();
|
||||
|
||||
let file: File | undefined = $state();
|
||||
let file: File | undefined = $state();
|
||||
|
||||
const dispatch = createEventDispatcher<{ upload: void }>();
|
||||
const dispatch = createEventDispatcher<{ upload: void; taskReload: void }>();
|
||||
|
||||
type Result = {
|
||||
class: string,
|
||||
confidence: number,
|
||||
}
|
||||
let _result: Promise<Task> = $state(new Promise(() => {}));
|
||||
let run = $state(false);
|
||||
|
||||
let _result: Promise<Result | undefined> = $state(new Promise(() => {}));
|
||||
let run = $state(false);
|
||||
let last_task: string | undefined = $state();
|
||||
let last_task: string | undefined = $state();
|
||||
let last_task_timeout: number | null = null;
|
||||
|
||||
let messages: MessageSimple;
|
||||
let messages: MessageSimple;
|
||||
|
||||
async function submit() {
|
||||
if (!file) return;
|
||||
messages.clear();
|
||||
async function reloadLastTimeout() {
|
||||
if (!last_task) {
|
||||
return;
|
||||
}
|
||||
last_task_timeout = null;
|
||||
|
||||
let form = new FormData();
|
||||
form.append("json_data", JSON.stringify({id: model.id}));
|
||||
form.append("file", file, "file");
|
||||
try {
|
||||
const r = await post('tasks/task', { id: last_task });
|
||||
if ([0, 1, 2, 3].includes(r.status)) {
|
||||
setTimeout(reloadLastTimeout, 500);
|
||||
setTimeout(() => dispatch('taskReload'), 500);
|
||||
} else {
|
||||
_result = Promise.resolve(r);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to get data');
|
||||
}
|
||||
}
|
||||
|
||||
run = true;
|
||||
|
||||
try {
|
||||
const r = await postFormData('tasks/start/image', form);
|
||||
last_task = r.id
|
||||
file = undefined;
|
||||
} catch (e) {
|
||||
if (e instanceof Response) {
|
||||
messages.display(await e.json());
|
||||
} else {
|
||||
messages.display("Could not run the model");
|
||||
}
|
||||
}
|
||||
async function submit() {
|
||||
if (!file) return;
|
||||
messages.clear();
|
||||
|
||||
dispatch('upload');
|
||||
}
|
||||
let form = new FormData();
|
||||
form.append('json_data', JSON.stringify({ id: model.id }));
|
||||
form.append('file', file, 'file');
|
||||
|
||||
run = true;
|
||||
|
||||
try {
|
||||
const r = await postFormData('tasks/start/image', form);
|
||||
last_task = r.id;
|
||||
file = undefined;
|
||||
last_task_timeout = setTimeout(() => reloadLastTimeout());
|
||||
} catch (e) {
|
||||
if (e instanceof Response) {
|
||||
messages.display(await e.json());
|
||||
} else {
|
||||
messages.display('Could not run the model');
|
||||
}
|
||||
}
|
||||
|
||||
dispatch('upload');
|
||||
}
|
||||
|
||||
onDestroy(() => {
|
||||
if (last_task_timeout) {
|
||||
clearTimeout(last_task_timeout);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<form on:submit|preventDefault={submit}>
|
||||
<fieldset class="file-upload" >
|
||||
<label for="file">Image</label>
|
||||
<div class="form-msg">
|
||||
Run image through them model and get the result
|
||||
</div>
|
||||
|
||||
<FileUpload replace_slot bind:file accept="image/*" >
|
||||
<img src="/imgs/upload-icon.png" alt="" />
|
||||
<span>
|
||||
Upload image
|
||||
</span>
|
||||
<div slot="replaced-name">
|
||||
<span>
|
||||
Image selected
|
||||
</span>
|
||||
</div>
|
||||
</FileUpload>
|
||||
</fieldset>
|
||||
<MessageSimple bind:this={messages} />
|
||||
<button>
|
||||
Run
|
||||
</button>
|
||||
{#if run}
|
||||
{#await _result}
|
||||
<h1>
|
||||
Processing Image {last_task}
|
||||
</h1>
|
||||
{:then result}
|
||||
{#if !result}
|
||||
<div class="result">
|
||||
<h1>
|
||||
The class was not found
|
||||
</h1>
|
||||
</div>
|
||||
{:else}
|
||||
<div>
|
||||
<h1>
|
||||
Result
|
||||
</h1>
|
||||
The image was classified as {result.class} with confidence: {result.confidence}
|
||||
</div>
|
||||
{/if}
|
||||
{/await}
|
||||
{/if}
|
||||
</form>
|
||||
<form on:submit|preventDefault={submit}>
|
||||
<fieldset class="file-upload">
|
||||
<label for="file">Image</label>
|
||||
<div class="form-msg">Run image through them model and get the result</div>
|
||||
|
||||
<FileUpload replace_slot bind:file accept="image/*">
|
||||
<img src="/imgs/upload-icon.png" alt="" />
|
||||
<span> Upload image </span>
|
||||
<div slot="replaced-name">
|
||||
<span> Image selected </span>
|
||||
</div>
|
||||
</FileUpload>
|
||||
</fieldset>
|
||||
<MessageSimple bind:this={messages} />
|
||||
<button> Run </button>
|
||||
{#if run}
|
||||
{#await _result}
|
||||
<h1>
|
||||
Processing Image! <Spinner />
|
||||
</h1>
|
||||
{:then result}
|
||||
{#if result.status == 4}
|
||||
{@const res = JSON.parse(result.result)}
|
||||
<div>
|
||||
<h1>Result</h1>
|
||||
The image was classified as {res.class} with confidence: {res.confidence}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="result">
|
||||
<h1>There was a problem running the task:</h1>
|
||||
{result?.status_message}
|
||||
</div>
|
||||
{/if}
|
||||
{/await}
|
||||
{/if}
|
||||
</form>
|
||||
|
@ -1,16 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { post } from "src/lib/requests.svelte";
|
||||
import type { Model } from "src/routes/models/edit/+page.svelte";
|
||||
import RunModel from "./RunModel.svelte";
|
||||
import TasksTable from "./TasksTable.svelte";
|
||||
import { post } from 'src/lib/requests.svelte';
|
||||
import type { Model } from 'src/routes/models/edit/+page.svelte';
|
||||
import RunModel from './RunModel.svelte';
|
||||
import TasksTable from './TasksTable.svelte';
|
||||
|
||||
const { active, model } = $props<{ active?: boolean, model: Model }>();
|
||||
const { active, model } = $props<{ active?: boolean; model: Model }>();
|
||||
|
||||
let table: TasksTable;
|
||||
let table: TasksTable;
|
||||
</script>
|
||||
|
||||
|
||||
<div class="content" class:selected={active}>
|
||||
<RunModel model={model} on:upload={() => table.getList()} />
|
||||
<TasksTable model={model} bind:this={table} />
|
||||
<RunModel {model} on:upload={() => table.getList()} on:taskReload={() => table.getList()} />
|
||||
<TasksTable {model} bind:this={table} />
|
||||
</div>
|
||||
|
@ -8,8 +8,26 @@
|
||||
user_confirmed: number;
|
||||
compacted: number;
|
||||
type: number;
|
||||
created: string;
|
||||
result: string;
|
||||
created: string;
|
||||
result: string;
|
||||
};
|
||||
export const TaskType = {
|
||||
TASK_FAILED_RUNNING: -2,
|
||||
TASK_FAILED_CREATION: -1,
|
||||
TASK_PREPARING: 0,
|
||||
TASK_TODO: 1,
|
||||
TASK_PICKED_UP: 2,
|
||||
TASK_RUNNING: 3,
|
||||
TASK_DONE: 4
|
||||
};
|
||||
export const TaskTypeStrings: Record<number, string> = {
|
||||
[-2]: 'Task failed running',
|
||||
[-1]: 'Failed to create task',
|
||||
0: 'Preparing task',
|
||||
1: 'Task to do',
|
||||
2: 'Task picked up by a runner',
|
||||
3: 'Task running',
|
||||
4: 'Task complete'
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -17,34 +35,34 @@
|
||||
import { post } from 'src/lib/requests.svelte';
|
||||
import type { Model } from './+page.svelte';
|
||||
|
||||
let { model } = $props<{ model: Model, uploadCounter?: number }>();
|
||||
let { model } = $props<{ model: Model; uploadCounter?: number }>();
|
||||
|
||||
let page = $state(0);
|
||||
let showNext = $state(false);
|
||||
let task_list = $state<Task[]>([]);
|
||||
|
||||
export async function getList() {
|
||||
export async function getList() {
|
||||
try {
|
||||
const res = await post('tasks/list', {
|
||||
id: model.id,
|
||||
page: page,
|
||||
});
|
||||
const res = await post('tasks/list', {
|
||||
id: model.id,
|
||||
page: page
|
||||
});
|
||||
showNext = res.show_next;
|
||||
task_list = res.task_list;
|
||||
} catch (e) {
|
||||
console.error('TODO notify user', e);
|
||||
}
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
if (model) {
|
||||
getList()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
if (model) {
|
||||
getList();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<h2>Tasks</h2>
|
||||
<h2>Tasks</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@ -63,11 +81,11 @@
|
||||
{#each task_list as task}
|
||||
<tr>
|
||||
<td>
|
||||
{#if task.type == 1}
|
||||
Image Run
|
||||
{:else}
|
||||
{task.type}
|
||||
{/if}
|
||||
{#if task.type == 1}
|
||||
Image Run
|
||||
{:else}
|
||||
{task.type}
|
||||
{/if}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{#if task.type == 1}
|
||||
@ -83,42 +101,42 @@
|
||||
{/if}
|
||||
</td>
|
||||
<td>
|
||||
{#if task.type == 1}
|
||||
{#if task.status == 4}
|
||||
{#if task.user_confirmed == 0}
|
||||
User has not agreed to the result of this task
|
||||
{:else if task.user_confirmed == -1}
|
||||
User has disagred with the result of this task
|
||||
{:else if task.user_confirmed == 1}
|
||||
User has aggred with the result of this task
|
||||
{:else}
|
||||
TODO {task.user_confirmed}
|
||||
{/if}
|
||||
{:else}
|
||||
-
|
||||
{/if}
|
||||
{:else}
|
||||
TODO Handle {task.type}
|
||||
{/if}
|
||||
{#if task.type == 1}
|
||||
{#if task.status == 4}
|
||||
{#if task.user_confirmed == 0}
|
||||
User has not agreed to the result of this task
|
||||
{:else if task.user_confirmed == -1}
|
||||
User has disagred with the result of this task
|
||||
{:else if task.user_confirmed == 1}
|
||||
User has aggred with the result of this task
|
||||
{:else}
|
||||
TODO {task.user_confirmed}
|
||||
{/if}
|
||||
{:else}
|
||||
-
|
||||
{/if}
|
||||
{:else}
|
||||
TODO Handle {task.type}
|
||||
{/if}
|
||||
</td>
|
||||
<td>
|
||||
{#if task.status == 4}
|
||||
{#if task.type == 1}
|
||||
{@const temp = JSON.parse(task.result)}
|
||||
{temp.class}({temp.confidence * 100}%)
|
||||
{:else}
|
||||
{task.result}
|
||||
{/if}
|
||||
{/if}
|
||||
<td>
|
||||
{#if task.status == 4}
|
||||
{#if task.type == 1}
|
||||
{@const temp = JSON.parse(task.result)}
|
||||
{temp.class}({temp.confidence * 100}%)
|
||||
{:else}
|
||||
{task.result}
|
||||
{/if}
|
||||
{/if}
|
||||
</td>
|
||||
<td>
|
||||
{task.status}
|
||||
<td>
|
||||
{TaskTypeStrings[task.status]}
|
||||
</td>
|
||||
<td>
|
||||
{task.status_message}
|
||||
<td>
|
||||
{task.status_message}
|
||||
</td>
|
||||
<td>
|
||||
{(new Date(task.created)).toLocaleString()}
|
||||
<td>
|
||||
{new Date(task.created).toLocaleString()}
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
|
Loading…
Reference in New Issue
Block a user