chore: improve the result in classification closes #34

This commit is contained in:
Andre Henriques 2024-04-13 14:21:38 +01:00
parent 3f828ab855
commit f8bc8ad85a
7 changed files with 250 additions and 169 deletions

6
db.go
View File

@ -1,6 +0,0 @@
package main
import (
)

View File

@ -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,29 +53,29 @@ 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)
} }
} }
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
View File

@ -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()
} }

View 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

View File

@ -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;
try { messages.clear();
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");
}
}
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> </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>

View File

@ -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>

View File

@ -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}