chore: did more clean up

This commit is contained in:
Andre Henriques 2024-04-14 15:19:32 +01:00
parent 8b13afba48
commit e7eeccd09e
20 changed files with 283 additions and 352 deletions

View File

@ -0,0 +1,8 @@
package dbtypes
type DATA_POINT_MODE int
const (
DATA_POINT_MODE_TRAINING DATA_POINT_MODE = 1
DATA_POINT_MODE_TESTING = 2
)

View File

@ -1,4 +1,4 @@
package models_utils package dbtypes
import ( import (
"database/sql" "database/sql"
@ -100,10 +100,10 @@ func GetBaseModel(db *sql.DB, id string) (base *BaseModel, err error) {
} }
func (m BaseModel) CanEval() bool { func (m BaseModel) CanEval() bool {
if m.Status != READY && m.Status != READY_RETRAIN && m.Status != READY_RETRAIN_FAILED && m.Status != READY_ALTERATION && m.Status != READY_ALTERATION_FAILED { if m.Status != READY && m.Status != READY_RETRAIN && m.Status != READY_RETRAIN_FAILED && m.Status != READY_ALTERATION && m.Status != READY_ALTERATION_FAILED {
return false return false
} }
return true return true
} }
func StringToImageMode(colorMode string) int { func StringToImageMode(colorMode string) int {

View File

@ -11,7 +11,7 @@ import (
"os" "os"
"path" "path"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
) )

View File

@ -3,6 +3,8 @@ package model_classes
import ( import (
"database/sql" "database/sql"
"errors" "errors"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
) )
var FailedToGetIdAfterInsertError = errors.New("Failed to Get Id After Insert Error") var FailedToGetIdAfterInsertError = errors.New("Failed to Get Id After Insert Error")
@ -23,6 +25,6 @@ func AddDataPoint(db *sql.DB, class_id string, file_path string, mode DATA_POINT
} }
func UpdateDataPointStatus(db *sql.DB, data_point_id string, status int, message *string) (err error) { func UpdateDataPointStatus(db *sql.DB, data_point_id string, status int, message *string) (err error) {
_, err = db.Exec("update model_data_point set status=$1, status_message=$2 where id=$3", status, message, data_point_id) _, err = db.Exec("update model_data_point set status=$1, status_message=$2 where id=$3", status, message, data_point_id)
return return
} }

View File

@ -1,43 +1,26 @@
package model_classes package model_classes
import ( import (
"strconv"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
) )
func HandleList(handle *Handle) { func HandleList(handle *Handle) {
handle.Get("/models/data/list", func(c *Context) *Error { type DataList struct {
if !c.CheckAuthLevel(1) { Id string `json:"id" validate:"required"`
return nil Page int `json:"page"`
} }
PostAuthJson(handle, "/models/data/list", User_Normal, func(c *Context, dat *DataList) *Error {
id, err := GetIdFromUrl(c, "id")
if err != nil {
return c.JsonBadRequest("Model Class not found!")
}
page := 0
if c.R.URL.Query().Has("page") {
page_url := c.R.URL.Query().Get("page")
page_url_number, err := strconv.Atoi(page_url)
if err != nil {
return c.JsonBadRequest("Page is not a number")
}
page = page_url_number
}
var class_row struct { var class_row struct {
Name string Name string
Model_id string Model_id string
} }
err = GetDBOnce(c, &class_row, "model_classes where id=$1", id) err := GetDBOnce(c, &class_row, "model_classes where id=$1", dat.Id)
if err == NotFoundError { if err == NotFoundError {
return c.JsonBadRequest("Model Class not found!") return c.JsonBadRequest("Model Class not found!")
} else if err != nil { } else if err != nil {
return c.Error500(err) return c.E500M("Failed to get classes", err)
} }
type baserow struct { type baserow struct {
@ -47,23 +30,21 @@ func HandleList(handle *Handle) {
Status int `json:"status"` Status int `json:"status"`
} }
rows, err := GetDbMultitple[baserow](c, "model_data_point where class_id=$1 limit 11 offset $2", id, page*10) rows, err := GetDbMultitple[baserow](c, "model_data_point where class_id=$1 limit 11 offset $2", dat.Id, dat.Page*10)
if err != nil { if err != nil {
return c.Error500(err) return c.E500M("Failed to get classes", err)
}
type ReturnType struct {
ImageList []*baserow `json:"image_list"`
Page int `json:"page"`
ShowNext bool `json:"showNext"`
} }
max_len := min(11, len(rows)) max_len := min(11, len(rows))
c.ShowMessage = false c.ShowMessage = false
return c.SendJSON(ReturnType{ return c.SendJSON(struct {
ImageList []*baserow `json:"image_list"`
Page int `json:"page"`
ShowNext bool `json:"showNext"`
}{
ImageList: rows[0:max_len], ImageList: rows[0:max_len],
Page: page, Page: dat.Page,
ShowNext: len(rows) == 11, ShowNext: len(rows) == 11,
}) })
}) })

View File

@ -1,8 +0,0 @@
package model_classes
type DATA_POINT_MODE int
const (
DATA_POINT_MODE_TRAINING DATA_POINT_MODE = 1
DATA_POINT_MODE_TESTING = 2
)

View File

@ -14,7 +14,6 @@ import (
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
model_classes "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/classes" model_classes "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/classes"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
) )
@ -68,9 +67,9 @@ func fileProcessor(
parts := strings.Split(file.Name, "/") parts := strings.Split(file.Name, "/")
mode := model_classes.DATA_POINT_MODE_TRAINING mode := DATA_POINT_MODE_TRAINING
if parts[0] == "testing" { if parts[0] == "testing" {
mode = model_classes.DATA_POINT_MODE_TESTING mode = DATA_POINT_MODE_TESTING
} }
data_point_id, err := model_classes.AddDataPoint(c.Db, ids[parts[1]], "id://", mode) data_point_id, err := model_classes.AddDataPoint(c.Db, ids[parts[1]], "id://", mode)

View File

@ -6,7 +6,6 @@ import (
"path" "path"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
) )
@ -14,44 +13,35 @@ func deleteModelJSON(c *Context, id string) *Error {
c.Logger.Warnf("Removing model with id: %s", id) c.Logger.Warnf("Removing model with id: %s", id)
_, err := c.Db.Exec("delete from models where id=$1;", id) _, err := c.Db.Exec("delete from models where id=$1;", id)
if err != nil { if err != nil {
return c.Error500(err) return c.E500M("Failed to delete models", err)
} }
model_path := path.Join("./savedData", id) model_path := path.Join("./savedData", id)
c.Logger.Warnf("Removing folder of model with id: %s at %s", id, model_path) c.Logger.Warnf("Removing folder of model with id: %s at %s", id, model_path)
err = os.RemoveAll(model_path) err = os.RemoveAll(model_path)
if err != nil { if err != nil {
return c.Error500(err) return c.E500M("Failed to remove data", err)
} }
return c.SendJSON(id) return c.SendJSON(id)
} }
func handleDelete(handle *Handle) { func handleDelete(handle *Handle) {
handle.Delete("/models/delete", func(c *Context) *Error { type DeleteModel struct {
if !c.CheckAuthLevel(1) { Id string `json:"id" validate:"required"`
return nil Name *string `json:"name,omitempty"`
} }
var dat struct { DeleteAuthJson(handle, "/models/delete", User_Normal, func(c *Context, dat *DeleteModel) *Error {
Id string `json:"id" validate:"required"`
Name *string `json:"name,omitempty"`
}
if err_ := c.ToJSON(&dat); err_ != nil {
return err_
}
var model struct { var model struct {
Id string Id string
Name string Name string
Status int Status int
} }
err := GetDBOnce(c, &model, "models where id=$1 and user_id=$2;", dat.Id, c.User.Id) err := GetDBOnce(c, &model, "models where id=$1 and user_id=$2;", dat.Id, c.User.Id)
if err == NotFoundError { if err == NotFoundError {
return c.SendJSONStatus(http.StatusNotFound, "Model not found!") return c.SendJSONStatus(http.StatusNotFound, "Model not found!")
} else if err != nil { } else if err != nil {
return c.Error500(err) return c.E500M("Faield to get model", err)
} }
switch model.Status { switch model.Status {

View File

@ -5,7 +5,6 @@ import (
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
model_classes "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/classes" model_classes "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/classes"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
) )

View File

@ -6,15 +6,7 @@ import (
) )
// Auth level set when path is definied as 1 // Auth level set when path is definied as 1
func handleStats(c *Context) *Error { func handleStats(c *Context, b *JustId) *Error {
var b struct {
Id string `json:"id" validate:"required"`
}
if _err := c.ToJSON(&b); _err != nil {
return _err
}
type Row struct { type Row struct {
Name string `db:"mc.name" json:"name"` Name string `db:"mc.name" json:"name"`
Training string `db:"count(mdp.id) filter (where mdp.model_mode=1)" json:"training"` Training string `db:"count(mdp.id) filter (where mdp.model_mode=1)" json:"training"`
@ -23,7 +15,7 @@ func handleStats(c *Context) *Error {
rows, err := GetDbMultitple[Row](c, "model_data_point as mdp inner join model_classes as mc on mc.id=mdp.class_id where mc.model_id=$1 group by mc.name order by mc.name asc;", b.Id) rows, err := GetDbMultitple[Row](c, "model_data_point as mdp inner join model_classes as mc on mc.id=mdp.class_id where mc.model_id=$1 group by mc.name order by mc.name asc;", b.Id)
if err != nil { if err != nil {
return c.Error500(err) return c.E500M("Failed to get stats", err)
} }
c.ShowMessage = false c.ShowMessage = false
@ -50,5 +42,5 @@ func handleList(handle *Handle) {
return c.SendJSON(got) return c.SendJSON(got)
}) })
handle.PostAuth("/models/class/stats", 1, handleStats) PostAuthJson(handle, "/models/class/stats", User_Normal, handleStats)
} }

View File

@ -6,7 +6,6 @@ import (
"path" "path"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks/utils"
tf "github.com/galeone/tensorflow/tensorflow/go" tf "github.com/galeone/tensorflow/tensorflow/go"

View File

@ -6,7 +6,7 @@ import (
_ "image/png" _ "image/png"
"os" "os"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
) )

View File

@ -4,29 +4,17 @@ import (
"os" "os"
"path" "path"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
) )
func handleRest(handle *Handle) { func handleRest(handle *Handle) {
handle.Delete("/models/train/reset", func(c *Context) *Error { DeleteAuthJson(handle, "/models/train/reset", User_Normal, func(c *Context, dat *JustId) *Error {
if !c.CheckAuthLevel(1) {
return nil
}
var dat struct {
Id string `json:"id"`
}
if err := c.ToJSON(&dat); err != nil {
return err
}
model, err := GetBaseModel(c.Db, dat.Id) model, err := GetBaseModel(c.Db, dat.Id)
if err == ModelNotFoundError { if err == ModelNotFoundError {
return c.JsonBadRequest("Model not found") return c.JsonBadRequest("Model not found")
} else if err != nil { } else if err != nil {
// TODO improve response return c.E500M("Failed to get model", err)
return c.Error500(err)
} }
if model.Status != FAILED_PREPARING_TRAINING && model.Status != FAILED_TRAINING { if model.Status != FAILED_PREPARING_TRAINING && model.Status != FAILED_TRAINING {
@ -37,8 +25,7 @@ func handleRest(handle *Handle) {
_, err = c.Db.Exec("delete from model_definition where model_id=$1", model.Id) _, err = c.Db.Exec("delete from model_definition where model_id=$1", model.Id)
if err != nil { if err != nil {
// TODO improve response return c.E500M("Failed to delete model", err)
return c.Error500(err)
} }
ModelUpdateStatus(c, model.Id, CONFIRM_PRE_TRAINING) ModelUpdateStatus(c, model.Id, CONFIRM_PRE_TRAINING)

View File

@ -16,7 +16,6 @@ import (
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
model_classes "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/classes" model_classes "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/classes"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
"github.com/charmbracelet/log" "github.com/charmbracelet/log"
) )
@ -80,7 +79,7 @@ func generateCvs(c *Context, run_path string, model_id string) (count int, err e
} }
count = co.Count count = co.Count
data, err := c.Db.Query("select mdp.id, mc.class_order, mdp.file_path from model_data_point as mdp inner join model_classes as mc on mc.id = mdp.class_id where mc.model_id = $1 and mdp.model_mode=$2;", model_id, model_classes.DATA_POINT_MODE_TRAINING) data, err := c.Db.Query("select mdp.id, mc.class_order, mdp.file_path from model_data_point as mdp inner join model_classes as mc on mc.id = mdp.class_id where mc.model_id = $1 and mdp.model_mode=$2;", model_id, DATA_POINT_MODE_TRAINING)
if err != nil { if err != nil {
return return
} }
@ -139,7 +138,7 @@ func generateCvsExp(c *Context, run_path string, model_id string, doPanic bool)
return generateCvsExp(c, run_path, model_id, true) return generateCvsExp(c, run_path, model_id, true)
} }
data, err := c.Db.Query("select mdp.id, mc.class_order, mdp.file_path from model_data_point as mdp inner join model_classes as mc on mc.id = mdp.class_id where mc.model_id = $1 and mdp.model_mode=$2 and mc.status=$3;", model_id, model_classes.DATA_POINT_MODE_TRAINING, MODEL_CLASS_STATUS_TRAINING) data, err := c.Db.Query("select mdp.id, mc.class_order, mdp.file_path from model_data_point as mdp inner join model_classes as mc on mc.id = mdp.class_id where mc.model_id = $1 and mdp.model_mode=$2 and mc.status=$3;", model_id, DATA_POINT_MODE_TRAINING, MODEL_CLASS_STATUS_TRAINING)
if err != nil { if err != nil {
return return
} }
@ -303,7 +302,7 @@ func generateCvsExpandExp(c *Context, run_path string, model_id string, offset i
return generateCvsExpandExp(c, run_path, model_id, offset, true) return generateCvsExpandExp(c, run_path, model_id, offset, true)
} }
data, err := c.Db.Query("select mdp.id, mc.class_order, mdp.file_path from model_data_point as mdp inner join model_classes as mc on mc.id = mdp.class_id where mc.model_id = $1 and mdp.model_mode=$2 and mc.status=$3;", model_id, model_classes.DATA_POINT_MODE_TRAINING, MODEL_CLASS_STATUS_TRAINING) data, err := c.Db.Query("select mdp.id, mc.class_order, mdp.file_path from model_data_point as mdp inner join model_classes as mc on mc.id = mdp.class_id where mc.model_id = $1 and mdp.model_mode=$2 and mc.status=$3;", model_id, DATA_POINT_MODE_TRAINING, MODEL_CLASS_STATUS_TRAINING)
if err != nil { if err != nil {
return return
} }
@ -337,7 +336,7 @@ func generateCvsExpandExp(c *Context, run_path string, model_id string, offset i
// This is to load some extra data so that the model has more things to train on // This is to load some extra data so that the model has more things to train on
// //
data_other, err := c.Db.Query("select mdp.id, mc.class_order, mdp.file_path from model_data_point as mdp inner join model_classes as mc on mc.id = mdp.class_id where mc.model_id = $1 and mdp.model_mode=$2 and mc.status=$3 limit $4;", model_id, model_classes.DATA_POINT_MODE_TRAINING, MODEL_CLASS_STATUS_TRAINED, count*10) data_other, err := c.Db.Query("select mdp.id, mc.class_order, mdp.file_path from model_data_point as mdp inner join model_classes as mc on mc.id = mdp.class_id where mc.model_id = $1 and mdp.model_mode=$2 and mc.status=$3 limit $4;", model_id, DATA_POINT_MODE_TRAINING, MODEL_CLASS_STATUS_TRAINED, count*10)
if err != nil { if err != nil {
return return
} }

View File

@ -9,7 +9,6 @@ import (
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/models"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks/utils"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
) )
@ -48,7 +47,7 @@ func handleUpload(handler *Handle) {
ModelId string `json:"id" validate:"required"` ModelId string `json:"id" validate:"required"`
} }
_err := c.ParseJson(&requestData, json_data) _err := c.ParseJson(&requestData, json_data)
if _err != nil { if _err != nil {
return _err return _err
} }
@ -88,9 +87,9 @@ func handleUpload(handler *Handle) {
} }
id, err := InsertReturnId(c, &newTask, "tasks", "id") id, err := InsertReturnId(c, &newTask, "tasks", "id")
if err != nil { if err != nil {
return c.E500M("Error 500", err) return c.E500M("Error 500", err)
} }
save_path := path.Join("savedData", model.Id, "tasks") save_path := path.Join("savedData", model.Id, "tasks")
os.MkdirAll(save_path, os.ModePerm) os.MkdirAll(save_path, os.ModePerm)
@ -99,26 +98,28 @@ func handleUpload(handler *Handle) {
img_file, err := os.Create(img_path) img_file, err := os.Create(img_path)
if err != nil { if err != nil {
if _err := UpdateTaskStatus(c,id, -1, "Failed to create the file"); _err != nil { if _err := UpdateTaskStatus(c, id, -1, "Failed to create the file"); _err != nil {
c.Logger.Error("Failed to update tasks") c.Logger.Error("Failed to update tasks")
} }
return c.E500M("Failed to create the file", err) return c.E500M("Failed to create the file", err)
} }
defer img_file.Close() defer img_file.Close()
img_file.Write(file) img_file.Write(file)
if !TestImgForModel(c, model, img_path) { if !TestImgForModel(c, model, img_path) {
if _err := UpdateTaskStatus(c, id, -1, "The provided image is not a valid image for this model"); _err != nil { if _err := UpdateTaskStatus(c, id, -1, "The provided image is not a valid image for this model"); _err != nil {
c.Logger.Error("Failed to update tasks") c.Logger.Error("Failed to update tasks")
} }
return c.JsonBadRequest(struct { return c.JsonBadRequest(struct {
Message string `json:"message"` Message string `json:"message"`
Id string `json:"task_id"` Id string `json:"task_id"`
} { "Provided image does not match the model", id}) }{"Provided image does not match the model", id})
} }
UpdateStatus(c, "tasks", id, 1) UpdateStatus(c, "tasks", id, 1)
return c.SendJSON(struct {Id string `json:"id"`}{id}) return c.SendJSON(struct {
Id string `json:"id"`
}{id})
}) })
} }

View File

@ -3,7 +3,6 @@ package tasks
import ( import (
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
dbtypes "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" dbtypes "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks/utils"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
) )

View File

@ -11,7 +11,6 @@ import (
"time" "time"
dbtypes "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types" dbtypes "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils"
"github.com/charmbracelet/log" "github.com/charmbracelet/log"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -67,7 +66,7 @@ func (x *Handle) Get(path string, fn func(c *Context) *Error) {
x.gets = append(x.gets, HandleFunc{path, fn}) x.gets = append(x.gets, HandleFunc{path, fn})
} }
func (x *Handle) GetAuth(path string, authLevel int, fn func(c *Context) *Error) { func (x *Handle) GetAuth(path string, authLevel dbtypes.UserType, fn func(c *Context) *Error) {
inner_fn := func(c *Context) *Error { inner_fn := func(c *Context) *Error {
if !c.CheckAuthLevel(authLevel) { if !c.CheckAuthLevel(authLevel) {
return nil return nil
@ -80,7 +79,7 @@ func (x *Handle) Post(path string, fn func(c *Context) *Error) {
x.posts = append(x.posts, HandleFunc{path, fn}) x.posts = append(x.posts, HandleFunc{path, fn})
} }
func (x *Handle) PostAuth(path string, authLevel int, fn func(c *Context) *Error) { func (x *Handle) PostAuth(path string, authLevel dbtypes.UserType, fn func(c *Context) *Error) {
inner_fn := func(c *Context) *Error { inner_fn := func(c *Context) *Error {
if !c.CheckAuthLevel(authLevel) { if !c.CheckAuthLevel(authLevel) {
return nil return nil
@ -92,7 +91,7 @@ func (x *Handle) PostAuth(path string, authLevel int, fn func(c *Context) *Error
func PostAuthJson[T interface{}](x *Handle, path string, authLevel dbtypes.UserType, fn func(c *Context, obj *T) *Error) { func PostAuthJson[T interface{}](x *Handle, path string, authLevel dbtypes.UserType, fn func(c *Context, obj *T) *Error) {
inner_fn := func(c *Context) *Error { inner_fn := func(c *Context) *Error {
if !c.CheckAuthLevel(int(authLevel)) { if !c.CheckAuthLevel(authLevel) {
return nil return nil
} }
@ -112,7 +111,7 @@ func (x *Handle) Delete(path string, fn func(c *Context) *Error) {
x.deletes = append(x.deletes, HandleFunc{path, fn}) x.deletes = append(x.deletes, HandleFunc{path, fn})
} }
func (x *Handle) DeleteAuth(path string, authLevel int, fn func(c *Context) *Error) { func (x *Handle) DeleteAuth(path string, authLevel dbtypes.UserType, fn func(c *Context) *Error) {
inner_fn := func(c *Context) *Error { inner_fn := func(c *Context) *Error {
if !c.CheckAuthLevel(authLevel) { if !c.CheckAuthLevel(authLevel) {
return nil return nil
@ -122,7 +121,7 @@ func (x *Handle) DeleteAuth(path string, authLevel int, fn func(c *Context) *Err
x.posts = append(x.posts, HandleFunc{path, inner_fn}) x.posts = append(x.posts, HandleFunc{path, inner_fn})
} }
func DeleteAuthJson[T interface{}](x *Handle, path string, authLevel int, fn func(c *Context, obj *T) *Error) { func DeleteAuthJson[T interface{}](x *Handle, path string, authLevel dbtypes.UserType, fn func(c *Context, obj *T) *Error) {
inner_fn := func(c *Context) *Error { inner_fn := func(c *Context) *Error {
if !c.CheckAuthLevel(authLevel) { if !c.CheckAuthLevel(authLevel) {
return nil return nil
@ -160,13 +159,13 @@ func handleLoop(array []HandleFunc, context *Context) {
handleError(&Error{404, "Endpoint not found"}, context) handleError(&Error{404, "Endpoint not found"}, context)
} }
func (c *Context) CheckAuthLevel(authLevel int) bool { func (c *Context) CheckAuthLevel(authLevel dbtypes.UserType) bool {
if authLevel > 0 { if authLevel > 0 {
if c.User == nil { if c.User == nil {
contextlessLogoff(c.Writer) contextlessLogoff(c.Writer)
return false return false
} }
if c.User.UserType < authLevel { if c.User.UserType < int(authLevel) {
c.Writer.WriteHeader(http.StatusUnauthorized) c.Writer.WriteHeader(http.StatusUnauthorized)
e := c.SendJSON("Not Authorized") e := c.SendJSON("Not Authorized")
if e != nil { if e != nil {
@ -321,15 +320,15 @@ func (c Context) JsonErrorBadRequest(err error, dat any) *Error {
return c.SendJSONStatus(http.StatusBadRequest, dat) return c.SendJSONStatus(http.StatusBadRequest, dat)
} }
func (c *Context) GetModelFromId(id_path string) (*BaseModel, *Error) { func (c *Context) GetModelFromId(id_path string) (*dbtypes.BaseModel, *Error) {
id, err := GetIdFromUrl(c, id_path) id, err := GetIdFromUrl(c, id_path)
if err != nil { if err != nil {
return nil, c.SendJSONStatus(http.StatusNotFound, "Model not found") return nil, c.SendJSONStatus(http.StatusNotFound, "Model not found")
} }
model, err := GetBaseModel(c.Db, id) model, err := dbtypes.GetBaseModel(c.Db, id)
if err == ModelNotFoundError { if err == dbtypes.ModelNotFoundError {
return nil, c.SendJSONStatus(http.StatusNotFound, "Model not found") return nil, c.SendJSONStatus(http.StatusNotFound, "Model not found")
} else if err != nil { } else if err != nil {
return nil, c.Error500(err) return nil, c.Error500(err)

View File

@ -7,8 +7,8 @@ import (
"github.com/charmbracelet/log" "github.com/charmbracelet/log"
_ "github.com/lib/pq" _ "github.com/lib/pq"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/models"
models_utils "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks" . "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" . "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
@ -44,7 +44,7 @@ func main() {
handle := NewHandler(db, config) handle := NewHandler(db, config)
// TODO remove this before commiting // TODO remove this before commiting
_, err = db.Exec("update models set status=$1 where status=$2", models_utils.FAILED_TRAINING, models_utils.TRAINING) _, err = db.Exec("update models set status=$1 where status=$2", FAILED_TRAINING, TRAINING)
if err != nil && clear_db { if err != nil && clear_db {
log.Warn("Database might not be on") log.Warn("Database might not be on")
panic(err) panic(err)

View File

@ -188,7 +188,7 @@ func usersEndpints(db *sql.DB, handle *Handle) {
}) })
// TODO allow admin users to update this data // TODO allow admin users to update this data
handle.GetAuth("/user/info", int(dbtypes.User_Normal), func(c *Context) *Error { handle.GetAuth("/user/info", dbtypes.User_Normal, func(c *Context) *Error {
user, err := dbtypes.UserFromToken(c.Db, *c.Token) user, err := dbtypes.UserFromToken(c.Db, *c.Token)
if err != nil { if err != nil {
return c.E500M("Falied to get user data", err) return c.E500M("Falied to get user data", err)

View File

@ -2,21 +2,21 @@
export type Image = { export type Image = {
file_path: string; file_path: string;
mode: number; mode: number;
status: number; status: number;
id: string; id: string;
}; };
</script> </script>
<script lang="ts"> <script lang="ts">
import Tabs from 'src/lib/Tabs.svelte'; import Tabs from 'src/lib/Tabs.svelte';
import type { Class } from './ModelData.svelte'; import type { Class } from './ModelData.svelte';
import { get, postFormData, rdelete } from 'src/lib/requests.svelte'; import { post, postFormData, rdelete } 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 } from 'svelte';
const dispatch = createEventDispatcher<{reload: void}>(); const dispatch = createEventDispatcher<{ reload: void }>();
let selected_class: Class | undefined = $state(); let selected_class: Class | undefined = $state();
@ -37,11 +37,10 @@
async function getList() { async function getList() {
try { try {
let url = new URLSearchParams(); let res = await post('models/data/list', {
url.append('id', selected_class?.id ?? ''); id: selected_class?.id ?? '',
url.append('page', `${page}`); page: page
});
let res = await get('models/data/list?' + url.toString());
showNext = res.showNext; showNext = res.showNext;
image_list = res.image_list; image_list = res.image_list;
} catch (e) { } catch (e) {
@ -61,43 +60,42 @@
} }
}); });
let file: File | undefined = $state(); let file: File | undefined = $state();
let uploadImage: MessageSimple; let uploadImage: MessageSimple;
let uploading = $state(Promise.resolve()); let uploading = $state(Promise.resolve());
async function uploadZip() { async function uploadZip() {
uploadImage.clear(); uploadImage.clear();
if (!file) return; if (!file) return;
uploading = new Promise(() => {}); uploading = new Promise(() => {});
let form = new FormData(); let form = new FormData();
form.append('id', model.id); form.append('id', model.id);
form.append('file', file, 'upload.zip'); form.append('file', file, 'upload.zip');
try {
await postFormData('models/data/class/upload', form);
dispatch('reload');
} catch (e) {
if (e instanceof Response) {
uploadImage.display(await e.json());
} else {
uploadImage.display('');
}
}
uploading = Promise.resolve(); try {
} await postFormData('models/data/class/upload', form);
dispatch('reload');
function deleteDataPoint(id: string) { } catch (e) {
try { if (e instanceof Response) {
rdelete('models/data/point', { id }) uploadImage.display(await e.json());
getList() } else {
} catch (e) { uploadImage.display('');
}
}
uploading = Promise.resolve();
}
function deleteDataPoint(id: string) {
try {
rdelete('models/data/point', { id });
getList();
} catch (e) {
console.error('TODO notify user', e); console.error('TODO notify user', e);
} }
} }
</script> </script>
{#if classes.length == 0} {#if classes.length == 0}
@ -106,47 +104,48 @@
<Tabs active={classes[0]?.name} let:isActive> <Tabs active={classes[0]?.name} let:isActive>
<div class="buttons" slot="buttons" let:setActive let:isActive> <div class="buttons" slot="buttons" let:setActive let:isActive>
<!-- TODO Auto Load 1st --> <!-- TODO Auto Load 1st -->
<div> <div>
{#each classes as item} {#each classes as item}
<button <button
on:click={() => setActiveClass(item, setActive)} on:click={() => setActiveClass(item, setActive)}
class="tab" class="tab"
class:selected={isActive(item.name)} class:selected={isActive(item.name)}
> >
{item.name} {item.name}
{#if model.model_type == 2} {#if model.model_type == 2}
{#if item.status == 1} {#if item.status == 1}
<span class="bi bi-book" style="color: orange;" /> <span class="bi bi-book" style="color: orange;" />
{:else if item.status == 2} {:else if item.status == 2}
<span class="bi bi-book" style="color: green;" /> <span class="bi bi-book" style="color: green;" />
{:else if item.status == 3} {:else if item.status == 3}
<span class="bi bi-check" style="color: green;" /> <span class="bi bi-check" style="color: green;" />
{/if} {/if}
{/if} {/if}
</button> </button>
{/each} {/each}
</div> </div>
<button on:click={() => { <button
setActive("-----New Class-----")(); on:click={() => {
selected_class = undefined; setActive('-----New Class-----')();
}}> selected_class = undefined;
<span class="bi bi-plus" /> }}
</button> >
<span class="bi bi-plus" />
</button>
</div> </div>
{#if selected_class == undefined && isActive('-----New Class-----')} {#if selected_class == undefined && isActive('-----New Class-----')}
<div class="content selected"> <div class="content selected">
<h2> <h2>Add New Class</h2>
Add New Class <form on:submit|preventDefault={uploadZip}>
</h2> <fieldset class="file-upload">
<form on:submit|preventDefault={uploadZip}> <label for="file">Data file</label>
<fieldset class="file-upload" > <div class="form-msg">
<label for="file">Data file</label> Please provide a file that has the training and testing data<br />
<div class="form-msg"> The file must have 2 folders one with testing images and one with training images.
Please provide a file that has the training and testing data<br/> <br />
The file must have 2 folders one with testing images and one with training images. <br/> Each of the folders will contain the classes of the model. The folders must be the same
Each of the folders will contain the classes of the model. The folders must be the same in testing and training. in testing and training. The class folders must have the images for the classes.
The class folders must have the images for the classes. <pre>
<pre>
training\ training\
class1\ class1\
img1.png img1.png
@ -172,147 +171,132 @@
... ...
... ...
</pre> </pre>
</div> </div>
<FileUpload replace_slot bind:file={file} accept="application/zip" notExpand > <FileUpload replace_slot bind:file accept="application/zip" notExpand>
<img src="/imgs/upload-icon.png" alt="" /> <img src="/imgs/upload-icon.png" alt="" />
<span> <span> Upload Zip File </span>
Upload Zip File <div slot="replaced" style="display: inline;">
</span> <img src="/imgs/upload-icon.png" alt="" />
<div slot="replaced" style="display: inline;"> <span> File selected </span>
<img src="/imgs/upload-icon.png" alt="" /> </div>
<span> </FileUpload>
File selected </fieldset>
</span> <MessageSimple bind:this={uploadImage} />
</div> {#if file}
</FileUpload> {#await uploading}
</fieldset> <button disabled> Uploading </button>
<MessageSimple bind:this={uploadImage} /> {:then}
{#if file} <button> Add </button>
{#await uploading} {/await}
<button disabled> {/if}
Uploading </form>
</button> </div>
{:then} {/if}
<button> {#if selected_class}
Add <div class="content selected">
</button> {#if model.model_type == 2}
{/await} {#if selected_class?.status == 1}
{/if} <h2>Class to train</h2>
</form> {:else if selected_class?.status == 2}
</div> <h2>Class training</h2>
{/if} {:else if selected_class?.status == 3}
{#if selected_class} <h2>Class trained</h2>
<div class="content selected"> {/if}
{#if model.model_type == 2} {/if}
{#if selected_class?.status == 1} <table>
<h2> <thead>
Class to train <tr>
</h2> <th> File Path </th>
{:else if selected_class?.status == 2} <th> Mode </th>
<h2> <th>
Class training <!-- Img -->
</h2> </th>
{:else if selected_class?.status == 3} <th>
<h2> <!-- Status -->
Class trained </th>
</h2> <th>
{/if} <!-- Remove -->
{/if} </th>
<table> </tr>
<thead> </thead>
<tr> <tbody>
<th> File Path </th> {#each image_list as image}
<th> Mode </th> <tr>
<th> <td>
<!-- Img --> {#if image.file_path == 'id://'}
</th> Managed
<th> {:else}
<!-- Status --> {image.file_path}
</th> {/if}
<th> </td>
<!-- Remove --> <td>
</th> {#if image.mode == 2}
</tr> Testing
</thead> {:else}
<tbody> Training
{#each image_list as image} {/if}
<tr> </td>
<td> <td class="text-center">
{#if image.file_path == 'id://'} {#if image.file_path == 'id://'}
Managed <img
{:else} alt=""
{image.file_path} src="/api/savedData/{model.id}/data/{image.id}.{model.format}"
{/if} height="30px"
</td> width="30px"
<td> style="object-fit: contain;"
{#if image.mode == 2} />
Testing {:else}
{:else} TODO img {image.file_path}
Training {/if}
{/if} </td>
</td> <td class="text-center">
<td class="text-center"> {#if image.status == 1}
{#if image.file_path == 'id://'} <span class="bi bi-check-circle-fill" style="color: green"></span>
<img {:else}
alt="" <span class="bi bi-exclamation-triangle-fill" style="color: red"></span>
src="/api/savedData/{model.id}/data/{image.id}.{model.format}" {/if}
height="30px" </td>
width="30px" <td style="width: 3ch">
style="object-fit: contain;" <button class="danger" on:click={() => deleteDataPoint(image.id)}>
/> <span class="bi bi-trash"></span>
{:else} </button>
TODO img {image.file_path} </td>
{/if} </tr>
</td> {/each}
<td class="text-center"> </tbody>
{#if image.status == 1} </table>
<span class="bi bi-check-circle-fill" style="color: green"></span> <div class="flex justify-center align-center">
{:else} <div class="grow-1 flex justify-end align-center">
<span class="bi bi-exclamation-triangle-fill" style="color: red"></span> {#if page > 0}
{/if} <button on:click={() => (page -= 1)}> Prev </button>
</td> {/if}
<td style="width: 3ch"> </div>
<button class="danger" on:click={() => deleteDataPoint(image.id)}>
<span class="bi bi-trash"></span>
</button>
</td>
</tr>
{/each}
</tbody>
</table>
<div class="flex justify-center align-center">
<div class="grow-1 flex justify-end align-center">
{#if page > 0}
<button on:click={() => (page -= 1)}> Prev </button>
{/if}
</div>
<div style="padding: 10px;"> <div style="padding: 10px;">
{page} {page}
</div> </div>
<div class="grow-1 flex justify-start align-center"> <div class="grow-1 flex justify-start align-center">
{#if showNext} {#if showNext}
<button on:click={() => (page += 1)}> Next </button> <button on:click={() => (page += 1)}> Next </button>
{/if} {/if}
</div> </div>
</div> </div>
</div> </div>
{/if} {/if}
</Tabs> </Tabs>
{/if} {/if}
<style lang="scss"> <style lang="scss">
.buttons {
.buttons { width: 100%;
width: 100%; display: flex;
display: flex; justify-content: space-between;
justify-content: space-between;
&>button { & > button {
margin: 3px 5px; margin: 3px 5px;
} }
} }
table { table {
width: 100%; width: 100%;