Add settings page

This commit is contained in:
Bartosz Karwacki 2022-01-23 13:45:56 +01:00
parent f75f3fded1
commit 7cff7f310a
14 changed files with 256 additions and 60 deletions

View File

@ -50,7 +50,7 @@ INSTALLED_APPS = [
"corsheaders",
"django_filters",
# apps
'cars'
"cars",
]
MIDDLEWARE = [
@ -156,3 +156,29 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# CORS
CORS_ALLOW_ALL_ORIGINS = True
PRODUCTION_YEAR = {
"low": [1960, 1960, 2001],
"mid": [1960, 2001, 2022],
"high": [2017, 2022, 2022],
}
MILEAGE = {
"low": [0, 0, 50000],
"mid": [0, 300000, 500000],
"high": [300000, 500000, 500000],
}
ENGINE_CAPACITY = {
"low": [0.7, 0.7, 1.2],
"mid": [1.2, 2.0, 8.2],
"high": [5.0, 8.2, 8.2],
}
COMBUSTION = {
"low": [4.0, 4.0, 6.0],
"mid": [4.0, 8.0, 15.0],
"high": [8.5, 15.0, 15.0],
}
COMPARATOR = 0.75

View File

@ -16,7 +16,4 @@ Including another URLconf
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("", include('cars.urls'))
]
urlpatterns = [path("admin/", admin.site.urls), path("", include("cars.urls"))]

View File

@ -2,5 +2,5 @@ from django.apps import AppConfig
class CarsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'cars'
default_auto_field = "django.db.models.BigAutoField"
name = "cars"

View File

@ -1,48 +1,83 @@
import numpy as np
import skfuzzy as fuzz
from skfuzzy import control as ctrl
from django.conf import settings
def get_fuzzy_response(request_params, objects_list):
# Stworzenie uniwersum
production_year = ctrl.Antecedent(np.arange(1960, 2022, 1), 'production_year')
mileage = ctrl.Antecedent(np.arange(0, 500000, 1), 'mileage')
engine_capacity = ctrl.Antecedent(np.arange(0.7, 8.2, 0.1), 'engine_capacity')
combustion = ctrl.Antecedent(np.arange(4.0, 15.0, 0.1), 'combustion')
production_year = ctrl.Antecedent(np.arange(1960, 2022, 1), "production_year")
mileage = ctrl.Antecedent(np.arange(0, 500000, 1), "mileage")
engine_capacity = ctrl.Antecedent(np.arange(0.7, 8.2, 0.1), "engine_capacity")
combustion = ctrl.Antecedent(np.arange(4.0, 15.0, 0.1), "combustion")
# Tworzenie funkcji rozmytych
production_year['low'] = fuzz.trimf(production_year.universe, [1960, 1960, 2001])
production_year['mid'] = fuzz.trimf(production_year.universe, [1960, 2001, 2022])
production_year['high'] = fuzz.trimf(production_year.universe, [2017, 2022, 2022])
production_year["low"] = fuzz.trimf(
production_year.universe, settings.PRODUCTION_YEAR["low"]
)
production_year["mid"] = fuzz.trimf(
production_year.universe, settings.PRODUCTION_YEAR["mid"]
)
production_year["high"] = fuzz.trimf(
production_year.universe, settings.PRODUCTION_YEAR["high"]
)
mileage['low'] = fuzz.trimf(mileage.universe, [0, 0, 50000])
mileage['mid'] = fuzz.trimf(mileage.universe, [0, 300000, 500000])
mileage['high'] = fuzz.trimf(mileage.universe, [300000, 500000, 500000])
mileage["low"] = fuzz.trimf(mileage.universe, settings.MILEAGE["low"])
mileage["mid"] = fuzz.trimf(mileage.universe, settings.MILEAGE["mid"])
mileage["high"] = fuzz.trimf(mileage.universe, settings.MILEAGE["high"])
engine_capacity['low'] = fuzz.trimf(engine_capacity.universe, [0.7, 0.7, 1.2])
engine_capacity['mid'] = fuzz.trimf(engine_capacity.universe, [1.2, 2.0, 8.2])
engine_capacity['high'] = fuzz.trimf(engine_capacity.universe, [5.0, 8.2, 8.2])
engine_capacity["low"] = fuzz.trimf(
engine_capacity.universe, settings.ENGINE_CAPACITY["low"]
)
engine_capacity["mid"] = fuzz.trimf(
engine_capacity.universe, settings.ENGINE_CAPACITY["mid"]
)
engine_capacity["high"] = fuzz.trimf(
engine_capacity.universe, settings.ENGINE_CAPACITY["high"]
)
combustion["low"] = fuzz.trimf(combustion.universe, settings.COMBUSTION["low"])
combustion["mid"] = fuzz.trimf(combustion.universe, settings.COMBUSTION["mid"])
combustion["high"] = fuzz.trimf(combustion.universe, settings.COMBUSTION["high"])
combustion['low'] = fuzz.trimf(combustion.universe, [4.0, 4.0, 6.0])
combustion['mid'] = fuzz.trimf(combustion.universe, [4.0, 8.0, 15.0])
combustion['high'] = fuzz.trimf(combustion.universe, [8.5, 15.0, 15.0])
# Obliczanie przynaleznosci danego obiektu do podanych danych kwerendy i tworzenie przefiltrowanej listy
end_object_list = []
for car in objects_list:
comparator = []
if 'production_year' in request_params:
comparator.append(fuzz.interp_membership(production_year.universe, production_year[str(request_params['production_year'])].mf, car.production_year))
if 'mileage' in request_params:
comparator.append(fuzz.interp_membership(mileage.universe, mileage[str(request_params['mileage'])].mf, car.mileage))
if 'engine_capacity' in request_params:
comparator.append(fuzz.interp_membership(engine_capacity.universe, engine_capacity[str(request_params['engine_capacity'])].mf, car.engine_capacity))
if 'combustion' in request_params:
comparator.append(fuzz.interp_membership(combustion.universe, combustion[str(request_params['combustion'])].mf, car.combustion))
if min(comparator) > 0.75:
if "production_year" in request_params:
comparator.append(
fuzz.interp_membership(
production_year.universe,
production_year[str(request_params["production_year"])].mf,
car.production_year,
)
)
if "mileage" in request_params:
comparator.append(
fuzz.interp_membership(
mileage.universe,
mileage[str(request_params["mileage"])].mf,
car.mileage,
)
)
if "engine_capacity" in request_params:
comparator.append(
fuzz.interp_membership(
engine_capacity.universe,
engine_capacity[str(request_params["engine_capacity"])].mf,
car.engine_capacity,
)
)
if "combustion" in request_params:
comparator.append(
fuzz.interp_membership(
combustion.universe,
combustion[str(request_params["combustion"])].mf,
car.combustion,
)
)
if min(comparator) > settings.COMPARATOR:
end_object_list.append(car)
return end_object_list
return end_object_list

View File

@ -1,5 +1,6 @@
from django.db import models
class Car(models.Model):
mark = models.CharField(max_length=150)
model = models.CharField(max_length=150)
@ -10,4 +11,4 @@ class Car(models.Model):
price = models.DecimalField(decimal_places=2, max_digits=16)
def __str__(self) -> str:
return "Car"
return "Car"

View File

@ -1,15 +1,16 @@
from rest_framework import serializers
from .models import Car
class CarSerializer(serializers.ModelSerializer):
class Meta:
class Meta:
model = Car
fields = [
'mark',
'model',
'mileage',
'production_year',
'engine_capacity',
'combustion',
'price'
]
"mark",
"model",
"mileage",
"production_year",
"engine_capacity",
"combustion",
"price",
]

View File

@ -1,7 +1,8 @@
from django.urls import path, include
from .views import CarList
from .views import CarList, SettingsAPIView
# The API URLs are now determined automatically by the router.
urlpatterns = [
path('cars', CarList.as_view()),
]
path("cars", CarList.as_view()),
path("settings", SettingsAPIView.as_view()),
]

View File

@ -1,25 +1,49 @@
VALUES = ['low', 'mid', 'high']
from django.conf import settings
VALUES = ["low", "mid", "high"]
def production_year_to_value(production_year):
return VALUES[["Dawno", "Średnio", "Niedawno"].index(production_year)]
def mileage_to_value(mileage):
return VALUES[["Niski", "Średni", "Duży"].index(mileage)]
def engine_capacity_to_value(engine_capacity):
return VALUES[["Mała", "Średnia", "Ogromna"].index(engine_capacity)]
def combustion_to_value(combustion):
return VALUES[["Niskie", "Średnie", "Wysokie"].index(combustion)]
def map_query_params(query_params):
values = {}
params = ['production_year', 'mileage', 'engine_capacity', 'combustion']
funcs = [production_year_to_value, mileage_to_value, engine_capacity_to_value, combustion_to_value]
params = ["production_year", "mileage", "engine_capacity", "combustion"]
funcs = [
production_year_to_value,
mileage_to_value,
engine_capacity_to_value,
combustion_to_value,
]
for param, func in zip(params, funcs):
if (query_param := query_params.get(param)):
if query_param := query_params.get(param):
values[param] = func(query_param)
return values
def set_settings_values(data):
settings.PRODUCTION_YEAR = get_values(data["production_year"])
settings.MILEAGE = get_values(data["mileage"])
settings.ENGINE_CAPACITY = get_values(data["engine_capacity"])
settings.COMBUSTION = get_values(data["combustion"])
settings.COMPARATOR = float(data["comparator"]["items"][0]["value"])
def get_values(label):
low = list(map(float, label["items"][0]["value"].split(",")))
mid = list(map(float, label["items"][1]["value"].split(",")))
high = list(map(float, label["items"][2]["value"].split(",")))
return {"low": low, "mid": mid, "high": high}

View File

@ -1,16 +1,25 @@
import re
from rest_framework import generics
from rest_framework.views import APIView
from rest_framework.response import Response
from .fuzzy_logic import get_fuzzy_response
from .models import Car
from .serializers import CarSerializer
from .utils import map_query_params
from .utils import map_query_params, set_settings_values
class CarList(generics.ListAPIView):
queryset = Car.objects.all()
serializer_class = CarSerializer
def list(self, request):
values = map_query_params(request.query_params)
response = get_fuzzy_response(values, self.get_queryset())
serializer = CarSerializer(response, many=True)
return Response(serializer.data)
return Response(serializer.data)
class SettingsAPIView(APIView):
def post(self, request, *args, **kwargs):
set_settings_values(request.data)
return Response("Settings changed")

View File

@ -1,6 +1,11 @@
<template>
<v-app-bar dense dark>
<v-app-bar-nav-icon></v-app-bar-nav-icon>
<v-app-bar-title>Systemy rozmyte</v-app-bar-title>
<template v-slot:extension>
<v-tabs align-with-title>
<v-tab to="/">Strona główna</v-tab>
<v-tab to="/settings">Ustawienia</v-tab>
</v-tabs>
</template>
</v-app-bar>
</template>

View File

@ -0,0 +1,75 @@
<template>
<v-container>
<v-row v-for="setting in settings" :key="setting.label">
<v-col md="12">
<h5>{{ setting.label }}</h5>
</v-col>
<v-col md="4" v-for="item in setting.items" :key="item.label">
<v-text-field v-model="item.value" :label="item.label"> </v-text-field>
</v-col>
</v-row>
<v-btn @click="changeSettings">Zmień ustawienia</v-btn>
</v-container>
</template>
<script>
import axios from 'axios';
export default {
name: "Table",
data: () => ({
settings: {
production_year: {
label: "Rok produkcji",
items: [
{ label: "Dawno", value: "1960,1960,2001" },
{ label: "Średnio", value: "1960,2001,2022" },
{ label: "Niedawno", value: "2017,2022,2022" },
],
},
mileage: {
label: "Przebieg",
items: [
{ label: "Niski", value: "0,0,50000" },
{ label: "Średni", value: "0,300000,500000" },
{ label: "Duży", value: "300000,500000,500000" },
],
},
engine_capacity: {
label: "Pojemność silnika",
items: [
{ label: "Mała", value: "0.7,0.7,1.2" },
{ label: "Średnia", value: "1.2,2.0,8.2" },
{ label: "Ogromna", value: "5.0,8.2,8.2" },
],
},
combustion: {
label: "Spalanie paliwa",
items: [
{ label: "Niskie", value: "4.0,4.0,6.0" },
{ label: "Średnie", value: "4.0,8.0,15.0" },
{ label: "Wysokie", value: "8.5,15.0,15.0" },
],
},
comparator: {
label: "Stopień przynależności",
items: [
{ label: "",
value: 0.75
}
],
}
},
}),
computed: {
},
methods: {
changeSettings() {
axios.post('http://localhost:8000/settings', this.settings)
}
}
};
</script>
<style scoped>
</style>

View File

@ -15,7 +15,7 @@ export default {
data: () => ({
headers: [
{ text: "Marka", value: "brand" },
{ text: "Marka", value: "mark" },
{ text: "Model", value: "model" },
{ text: "Przebieg (km)", value: "mileage" },
{ text: "Rok produkcji", value: "production_year" },

View File

@ -9,6 +9,11 @@ const routes = [
name: "Home",
component: () => import(/* webpackChunkName: "home" */ "../views/Home.vue"),
},
{
path: "/settings",
name: "Settings",
component: () => import(/* webpackChunkName: "home" */ "../views/Settings.vue"),
},
];
const router = new VueRouter({

View File

@ -0,0 +1,17 @@
<template>
<div>
<Settings class="my-5"/>
</div>
</template>
<script>
import Settings from "../components/Settings";
export default {
name: "Setting",
components: {
Settings,
},
};
</script>