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) {
|
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 {
|
handler.PostAuth("/tasks/list", 1, func(c *Context) *Error {
|
||||||
var err error = nil
|
var err error = nil
|
||||||
|
|
||||||
var requestData struct {
|
var requestData struct {
|
||||||
ModelId string `json:"model_id"`
|
ModelId string `json:"model_id"`
|
||||||
Page int `json:"page"`
|
Page int `json:"page"`
|
||||||
}
|
}
|
||||||
|
|
||||||
if _err := c.ToJSON(&requestData); _err != nil {
|
if _err := c.ToJSON(&requestData); _err != nil {
|
||||||
@ -33,15 +53,15 @@ func handleList(handler *Handle) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var rows []*Task = nil
|
var rows []*Task = nil
|
||||||
|
|
||||||
if requestData.ModelId != "" {
|
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 {
|
if err != nil {
|
||||||
return c.Error500(err)
|
return c.Error500(err)
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
if err != nil {
|
||||||
return c.Error500(err)
|
return c.Error500(err)
|
||||||
}
|
}
|
||||||
@ -49,13 +69,13 @@ func handleList(handler *Handle) {
|
|||||||
|
|
||||||
max_len := min(11, len(rows))
|
max_len := min(11, len(rows))
|
||||||
|
|
||||||
c.ShowMessage = false
|
c.ShowMessage = false
|
||||||
return c.SendJSON(struct {
|
return c.SendJSON(struct {
|
||||||
TaskList []*Task `json:"task_list"`
|
TaskList []*Task `json:"task_list"`
|
||||||
ShowNext bool `json:"show_next"`
|
ShowNext bool `json:"show_next"`
|
||||||
} {
|
}{
|
||||||
rows[0:max_len],
|
rows[0:max_len],
|
||||||
len(rows) > 10,
|
len(rows) > 10,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
12
main.go
12
main.go
@ -8,10 +8,10 @@ import (
|
|||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
|
|
||||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models"
|
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models"
|
||||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks"
|
|
||||||
models_utils "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils"
|
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/tasks/runner"
|
||||||
|
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -35,10 +35,10 @@ func main() {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
log.Info("Starting server on :5002!")
|
log.Info("Starting server on :5002!")
|
||||||
|
|
||||||
config := LoadConfig()
|
config := LoadConfig()
|
||||||
log.Info("Config loaded!", "config", config)
|
log.Info("Config loaded!", "config", config)
|
||||||
|
|
||||||
StartRunners(db, config)
|
StartRunners(db, config)
|
||||||
|
|
||||||
//TODO check if file structure exists to save data
|
//TODO check if file structure exists to save data
|
||||||
handle := NewHandler(db, config)
|
handle := NewHandler(db, config)
|
||||||
@ -59,7 +59,7 @@ func main() {
|
|||||||
|
|
||||||
usersEndpints(db, handle)
|
usersEndpints(db, handle)
|
||||||
HandleModels(handle)
|
HandleModels(handle)
|
||||||
HandleTasks(handle)
|
HandleTasks(handle)
|
||||||
|
|
||||||
handle.Startup()
|
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">
|
<script lang="ts">
|
||||||
import { postFormData } from "src/lib/requests.svelte";
|
import { post, postFormData } from 'src/lib/requests.svelte';
|
||||||
import type { Model } from "./+page.svelte";
|
import type { Model } from './+page.svelte';
|
||||||
import FileUpload from "src/lib/FileUpload.svelte";
|
import FileUpload from 'src/lib/FileUpload.svelte';
|
||||||
import MessageSimple from "src/lib/MessageSimple.svelte";
|
import MessageSimple from 'src/lib/MessageSimple.svelte';
|
||||||
import { createEventDispatcher } from "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 = {
|
let _result: Promise<Task> = $state(new Promise(() => {}));
|
||||||
class: string,
|
let run = $state(false);
|
||||||
confidence: number,
|
|
||||||
}
|
|
||||||
|
|
||||||
let _result: Promise<Result | undefined> = $state(new Promise(() => {}));
|
let last_task: string | undefined = $state();
|
||||||
let run = $state(false);
|
let last_task_timeout: number | null = null;
|
||||||
let last_task: string | undefined = $state();
|
|
||||||
|
|
||||||
let messages: MessageSimple;
|
let messages: MessageSimple;
|
||||||
|
|
||||||
async function submit() {
|
async function reloadLastTimeout() {
|
||||||
if (!file) return;
|
if (!last_task) {
|
||||||
messages.clear();
|
return;
|
||||||
|
}
|
||||||
|
last_task_timeout = null;
|
||||||
|
|
||||||
let form = new FormData();
|
try {
|
||||||
form.append("json_data", JSON.stringify({id: model.id}));
|
const r = await post('tasks/task', { id: last_task });
|
||||||
form.append("file", file, "file");
|
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;
|
async function submit() {
|
||||||
|
if (!file) return;
|
||||||
|
messages.clear();
|
||||||
|
|
||||||
try {
|
let form = new FormData();
|
||||||
const r = await postFormData('tasks/start/image', form);
|
form.append('json_data', JSON.stringify({ id: model.id }));
|
||||||
last_task = r.id
|
form.append('file', file, 'file');
|
||||||
file = undefined;
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof Response) {
|
|
||||||
messages.display(await e.json());
|
|
||||||
} else {
|
|
||||||
messages.display("Could not run the model");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch('upload');
|
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>
|
</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/*" >
|
<form on:submit|preventDefault={submit}>
|
||||||
<img src="/imgs/upload-icon.png" alt="" />
|
<fieldset class="file-upload">
|
||||||
<span>
|
<label for="file">Image</label>
|
||||||
Upload image
|
<div class="form-msg">Run image through them model and get the result</div>
|
||||||
</span>
|
|
||||||
<div slot="replaced-name">
|
<FileUpload replace_slot bind:file accept="image/*">
|
||||||
<span>
|
<img src="/imgs/upload-icon.png" alt="" />
|
||||||
Image selected
|
<span> Upload image </span>
|
||||||
</span>
|
<div slot="replaced-name">
|
||||||
</div>
|
<span> Image selected </span>
|
||||||
</FileUpload>
|
</div>
|
||||||
</fieldset>
|
</FileUpload>
|
||||||
<MessageSimple bind:this={messages} />
|
</fieldset>
|
||||||
<button>
|
<MessageSimple bind:this={messages} />
|
||||||
Run
|
<button> Run </button>
|
||||||
</button>
|
{#if run}
|
||||||
{#if run}
|
{#await _result}
|
||||||
{#await _result}
|
<h1>
|
||||||
<h1>
|
Processing Image! <Spinner />
|
||||||
Processing Image {last_task}
|
</h1>
|
||||||
</h1>
|
{:then result}
|
||||||
{:then result}
|
{#if result.status == 4}
|
||||||
{#if !result}
|
{@const res = JSON.parse(result.result)}
|
||||||
<div class="result">
|
<div>
|
||||||
<h1>
|
<h1>Result</h1>
|
||||||
The class was not found
|
The image was classified as {res.class} with confidence: {res.confidence}
|
||||||
</h1>
|
</div>
|
||||||
</div>
|
{:else}
|
||||||
{:else}
|
<div class="result">
|
||||||
<div>
|
<h1>There was a problem running the task:</h1>
|
||||||
<h1>
|
{result?.status_message}
|
||||||
Result
|
</div>
|
||||||
</h1>
|
{/if}
|
||||||
The image was classified as {result.class} with confidence: {result.confidence}
|
{/await}
|
||||||
</div>
|
{/if}
|
||||||
{/if}
|
</form>
|
||||||
{/await}
|
|
||||||
{/if}
|
|
||||||
</form>
|
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { post } from "src/lib/requests.svelte";
|
import { post } from 'src/lib/requests.svelte';
|
||||||
import type { Model } from "src/routes/models/edit/+page.svelte";
|
import type { Model } from 'src/routes/models/edit/+page.svelte';
|
||||||
import RunModel from "./RunModel.svelte";
|
import RunModel from './RunModel.svelte';
|
||||||
import TasksTable from "./TasksTable.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>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<div class="content" class:selected={active}>
|
<div class="content" class:selected={active}>
|
||||||
<RunModel model={model} on:upload={() => table.getList()} />
|
<RunModel {model} on:upload={() => table.getList()} on:taskReload={() => table.getList()} />
|
||||||
<TasksTable model={model} bind:this={table} />
|
<TasksTable {model} bind:this={table} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,8 +8,26 @@
|
|||||||
user_confirmed: number;
|
user_confirmed: number;
|
||||||
compacted: number;
|
compacted: number;
|
||||||
type: number;
|
type: number;
|
||||||
created: string;
|
created: string;
|
||||||
result: 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>
|
</script>
|
||||||
|
|
||||||
@ -17,34 +35,34 @@
|
|||||||
import { post } from 'src/lib/requests.svelte';
|
import { post } from 'src/lib/requests.svelte';
|
||||||
import type { Model } from './+page.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 page = $state(0);
|
||||||
let showNext = $state(false);
|
let showNext = $state(false);
|
||||||
let task_list = $state<Task[]>([]);
|
let task_list = $state<Task[]>([]);
|
||||||
|
|
||||||
export async function getList() {
|
export async function getList() {
|
||||||
try {
|
try {
|
||||||
const res = await post('tasks/list', {
|
const res = await post('tasks/list', {
|
||||||
id: model.id,
|
id: model.id,
|
||||||
page: page,
|
page: page
|
||||||
});
|
});
|
||||||
showNext = res.show_next;
|
showNext = res.show_next;
|
||||||
task_list = res.task_list;
|
task_list = res.task_list;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('TODO notify user', e);
|
console.error('TODO notify user', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (model) {
|
if (model) {
|
||||||
getList()
|
getList();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h2>Tasks</h2>
|
<h2>Tasks</h2>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -63,11 +81,11 @@
|
|||||||
{#each task_list as task}
|
{#each task_list as task}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
{#if task.type == 1}
|
{#if task.type == 1}
|
||||||
Image Run
|
Image Run
|
||||||
{:else}
|
{:else}
|
||||||
{task.type}
|
{task.type}
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
{#if task.type == 1}
|
{#if task.type == 1}
|
||||||
@ -83,42 +101,42 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{#if task.type == 1}
|
{#if task.type == 1}
|
||||||
{#if task.status == 4}
|
{#if task.status == 4}
|
||||||
{#if task.user_confirmed == 0}
|
{#if task.user_confirmed == 0}
|
||||||
User has not agreed to the result of this task
|
User has not agreed to the result of this task
|
||||||
{:else if task.user_confirmed == -1}
|
{:else if task.user_confirmed == -1}
|
||||||
User has disagred with the result of this task
|
User has disagred with the result of this task
|
||||||
{:else if task.user_confirmed == 1}
|
{:else if task.user_confirmed == 1}
|
||||||
User has aggred with the result of this task
|
User has aggred with the result of this task
|
||||||
{:else}
|
{:else}
|
||||||
TODO {task.user_confirmed}
|
TODO {task.user_confirmed}
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
-
|
-
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
TODO Handle {task.type}
|
TODO Handle {task.type}
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{#if task.status == 4}
|
{#if task.status == 4}
|
||||||
{#if task.type == 1}
|
{#if task.type == 1}
|
||||||
{@const temp = JSON.parse(task.result)}
|
{@const temp = JSON.parse(task.result)}
|
||||||
{temp.class}({temp.confidence * 100}%)
|
{temp.class}({temp.confidence * 100}%)
|
||||||
{:else}
|
{:else}
|
||||||
{task.result}
|
{task.result}
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{task.status}
|
{TaskTypeStrings[task.status]}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{task.status_message}
|
{task.status_message}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{(new Date(task.created)).toLocaleString()}
|
{new Date(task.created).toLocaleString()}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
|
Loading…
Reference in New Issue
Block a user