From 7cff7f310ad2112cd45724c1d4e966db6d72d0b7 Mon Sep 17 00:00:00 2001 From: Bartosz Karwacki Date: Sun, 23 Jan 2022 13:45:56 +0100 Subject: [PATCH] Add settings page --- backend/backend/settings.py | 28 ++++++++- backend/backend/urls.py | 5 +- backend/cars/apps.py | 4 +- backend/cars/fuzzy_logic.py | 93 +++++++++++++++++++--------- backend/cars/models.py | 3 +- backend/cars/serializers.py | 19 +++--- backend/cars/urls.py | 7 ++- backend/cars/utils.py | 34 ++++++++-- backend/cars/views.py | 17 +++-- frontend/src/components/AppBar.vue | 7 ++- frontend/src/components/Settings.vue | 75 ++++++++++++++++++++++ frontend/src/components/Table.vue | 2 +- frontend/src/router/index.js | 5 ++ frontend/src/views/Settings.vue | 17 +++++ 14 files changed, 256 insertions(+), 60 deletions(-) create mode 100644 frontend/src/components/Settings.vue create mode 100644 frontend/src/views/Settings.vue diff --git a/backend/backend/settings.py b/backend/backend/settings.py index 3486fe2..7b74233 100644 --- a/backend/backend/settings.py +++ b/backend/backend/settings.py @@ -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 diff --git a/backend/backend/urls.py b/backend/backend/urls.py index 8584ead..3175ef0 100644 --- a/backend/backend/urls.py +++ b/backend/backend/urls.py @@ -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"))] diff --git a/backend/cars/apps.py b/backend/cars/apps.py index 51be0d4..9401e5b 100644 --- a/backend/cars/apps.py +++ b/backend/cars/apps.py @@ -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" diff --git a/backend/cars/fuzzy_logic.py b/backend/cars/fuzzy_logic.py index 4eba69c..f9ee3c1 100644 --- a/backend/cars/fuzzy_logic.py +++ b/backend/cars/fuzzy_logic.py @@ -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 diff --git a/backend/cars/models.py b/backend/cars/models.py index 60f60c8..c4b3e2f 100644 --- a/backend/cars/models.py +++ b/backend/cars/models.py @@ -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" \ No newline at end of file + return "Car" diff --git a/backend/cars/serializers.py b/backend/cars/serializers.py index 44eb340..b22d4e7 100644 --- a/backend/cars/serializers.py +++ b/backend/cars/serializers.py @@ -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' - ] \ No newline at end of file + "mark", + "model", + "mileage", + "production_year", + "engine_capacity", + "combustion", + "price", + ] diff --git a/backend/cars/urls.py b/backend/cars/urls.py index feaadf0..3269575 100644 --- a/backend/cars/urls.py +++ b/backend/cars/urls.py @@ -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()), -] \ No newline at end of file + path("cars", CarList.as_view()), + path("settings", SettingsAPIView.as_view()), +] diff --git a/backend/cars/utils.py b/backend/cars/utils.py index 7aa12bc..6f0a0d1 100644 --- a/backend/cars/utils.py +++ b/backend/cars/utils.py @@ -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 - \ No newline at end of file + + +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} diff --git a/backend/cars/views.py b/backend/cars/views.py index 81d48e4..e9c5ff0 100644 --- a/backend/cars/views.py +++ b/backend/cars/views.py @@ -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) \ No newline at end of file + return Response(serializer.data) + + +class SettingsAPIView(APIView): + def post(self, request, *args, **kwargs): + set_settings_values(request.data) + return Response("Settings changed") diff --git a/frontend/src/components/AppBar.vue b/frontend/src/components/AppBar.vue index a7c33f0..a566377 100644 --- a/frontend/src/components/AppBar.vue +++ b/frontend/src/components/AppBar.vue @@ -1,6 +1,11 @@ diff --git a/frontend/src/components/Settings.vue b/frontend/src/components/Settings.vue new file mode 100644 index 0000000..b457c14 --- /dev/null +++ b/frontend/src/components/Settings.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/frontend/src/components/Table.vue b/frontend/src/components/Table.vue index 3d9f4a8..80cbd77 100644 --- a/frontend/src/components/Table.vue +++ b/frontend/src/components/Table.vue @@ -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" }, diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index 0d9a3c1..edd9069 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -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({ diff --git a/frontend/src/views/Settings.vue b/frontend/src/views/Settings.vue new file mode 100644 index 0000000..b9abc68 --- /dev/null +++ b/frontend/src/views/Settings.vue @@ -0,0 +1,17 @@ + + +