Compare commits

...

7 Commits

Author SHA1 Message Date
Bartosz Karwacki
52649a0beb Lint 2022-01-23 19:07:02 +01:00
Bartosz Karwacki
41305d18cd Merge branch 'master' of git.wmi.amu.edu.pl:s470611/Systemy-rozmyte-sql 2022-01-23 19:06:26 +01:00
Bartosz Karwacki
370df82259 Settings from backend 2022-01-23 19:03:55 +01:00
Wojciech Jarmosz
9f8d758b6e Fixes for settings, insert scripts, table header and fuzzy logic 2022-01-23 18:57:40 +01:00
Wojciech Jarmosz
b3964b3a97 Add sql database insert scripts 2022-01-23 18:14:07 +01:00
Bartosz Karwacki
7cff7f310a Add settings page 2022-01-23 13:45:56 +01:00
f75f3fded1 Merge pull request 'fix_fuzzy_logic' (#1) from fix_fuzzy_logic into master
Reviewed-on: #1
2022-01-23 12:16:50 +01:00
16 changed files with 8237 additions and 104 deletions

View File

@ -50,7 +50,7 @@ INSTALLED_APPS = [
"corsheaders", "corsheaders",
"django_filters", "django_filters",
# apps # apps
'cars' "cars",
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@ -156,3 +156,29 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# CORS # CORS
CORS_ALLOW_ALL_ORIGINS = True 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

@ -14,9 +14,6 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.contrib import admin from django.contrib import admin
from django.urls import path, include from django.urls import include, path
urlpatterns = [ urlpatterns = [path("admin/", admin.site.urls), path("", include("cars.urls"))]
path("admin/", admin.site.urls),
path("", include('cars.urls'))
]

View File

@ -1,4 +1,5 @@
from django.contrib import admin from django.contrib import admin
from .models import Car from .models import Car
admin.site.register(Car) admin.site.register(Car)

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,9 @@
from django.urls import path, include from django.urls import include, path
from .views import CarList
from .views import CarList, SettingsAPIView
# The API URLs are now determined automatically by the router. # The API URLs are now determined automatically by the router.
urlpatterns = [ 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): def production_year_to_value(production_year):
return VALUES[["Dawno", "Średnio", "Niedawno"].index(production_year)] return VALUES[["Dawno", "Średnio", "Niedawno"].index(production_year)]
def mileage_to_value(mileage): def mileage_to_value(mileage):
return VALUES[["Niski", "Średni", "Duży"].index(mileage)] return VALUES[["Niski", "Średni", "Duży"].index(mileage)]
def engine_capacity_to_value(engine_capacity): def engine_capacity_to_value(engine_capacity):
return VALUES[["Mała", "Średnia", "Ogromna"].index(engine_capacity)] return VALUES[["Mała", "Średnia", "Ogromna"].index(engine_capacity)]
def combustion_to_value(combustion): def combustion_to_value(combustion):
return VALUES[["Niskie", "Średnie", "Wysokie"].index(combustion)] return VALUES[["Niskie", "Średnie", "Wysokie"].index(combustion)]
def map_query_params(query_params): def map_query_params(query_params):
values = {} values = {}
params = ['production_year', 'mileage', 'engine_capacity', 'combustion'] params = ["production_year", "mileage", "engine_capacity", "combustion"]
funcs = [production_year_to_value, mileage_to_value, engine_capacity_to_value, combustion_to_value] funcs = [
production_year_to_value,
mileage_to_value,
engine_capacity_to_value,
combustion_to_value,
]
for param, func in zip(params, funcs): 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) values[param] = func(query_param)
return values 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,37 @@
from django.conf import settings
from rest_framework import generics from rest_framework import generics
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView
from .fuzzy_logic import get_fuzzy_response from .fuzzy_logic import get_fuzzy_response
from .models import Car from .models import Car
from .serializers import CarSerializer from .serializers import CarSerializer
from .utils import map_query_params from .utils import map_query_params, set_settings_values
class CarList(generics.ListAPIView): class CarList(generics.ListAPIView):
queryset = Car.objects.all() queryset = Car.objects.all()
serializer_class = CarSerializer serializer_class = CarSerializer
def list(self, request): def list(self, request):
values = map_query_params(request.query_params) values = map_query_params(request.query_params)
response = get_fuzzy_response(values, self.get_queryset()) response = get_fuzzy_response(values, self.get_queryset())
serializer = CarSerializer(response, many=True) 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")
def get(self, request, *args, **kwargs):
return Response(
{
"production_year": settings.PRODUCTION_YEAR,
"mileage": settings.MILEAGE,
"engine_capacity": settings.ENGINE_CAPACITY,
"combustion": settings.COMBUSTION,
"comparator": settings.COMPARATOR,
}
)

View File

@ -1,6 +1,11 @@
<template> <template>
<v-app-bar dense dark> <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> <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> </v-app-bar>
</template> </template>

View File

@ -0,0 +1,87 @@
<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: "2000,2000,2009" },
{ label: "Średnio", value: "2009,2012,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: {},
created() {
this.getSettings();
},
methods: {
changeSettings() {
axios.post("http://localhost:8000/settings", this.settings);
},
setValuesToSettings(label, data) {
this.settings[label].items[0].value = data[label].low.join(',')
this.settings[label].items[1].value = data[label].mid.join(',')
this.settings[label].items[2].value = data[label].high.join(',')
},
async getSettings() {
const response = await axios.get("http://localhost:8000/settings");
const data = response.data;
this.settings.comparator.items[0].value = data.comparator
this.setValuesToSettings('production_year', data)
this.setValuesToSettings('mileage', data)
this.setValuesToSettings('combustion', data)
this.setValuesToSettings('engine_capacity', data)
},
},
};
</script>
<style scoped>
</style>

View File

@ -1,54 +1,58 @@
<template> <template>
<v-container> <v-container>
<v-row> <v-row>
<v-col md="12"> <v-col md="12">
<v-data-table :headers="headers" :items="getCars" class="elevation-1"></v-data-table> <v-data-table
</v-col> :headers="headers"
</v-row> :items="getCars"
</v-container> class="elevation-1"
></v-data-table>
</v-col>
</v-row>
</v-container>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters } from "vuex";
export default { export default {
name: "Table", name: "Table",
data: () => ({ data: () => ({
headers: [ headers: [
{ text: "Marka", value: "brand" }, { text: "Marka", value: "mark" },
{ text: "Model", value: "model" }, { text: "Model", value: "model" },
{ text: "Przebieg (km)", value: "mileage" }, { text: "Przebieg (km)", value: "mileage" },
{ text: "Rok produkcji", value: "production_year" }, { text: "Rok produkcji", value: "production_year" },
{ text: "Pojemnośc silnika (cm^3)", value: "engine_capacity" }, { text: "Pojemnośc silnika (cm^3)", value: "engine_capacity" },
{ text: "Spalanie (L/100km)", value: "combustion" }, { text: "Spalanie (L/100km)", value: "combustion" },
{ text: "Cena (zł)", value: "price" }, { text: "Cena (USD)", value: "price" },
], ],
items: [{ items: [
brand: "Ford", {
model: "Focus", brand: "Ford",
mileage: 230000, model: "Focus",
production_year: 2008, mileage: 230000,
engine_capacity: 2.0, production_year: 2008,
combustion: 7.6, engine_capacity: 2.0,
price: 12200, combustion: 7.6,
}, price: 12200,
{ },
brand: "Fiat", {
model: "Punto", brand: "Fiat",
mileage: 430000, model: "Punto",
production_year: 2003, mileage: 430000,
engine_capacity: 1.3, production_year: 2003,
combustion: 5.5, engine_capacity: 1.3,
price: 3500, combustion: 5.5,
}, price: 3500,
], },
}), ],
computed: { }),
...mapGetters(['getCars']) computed: {
} ...mapGetters(["getCars"]),
},
}; };
</script> </script>
<style scoped> <style scoped>
</style> </style>

View File

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

7906
insert-data.sql Normal file

File diff suppressed because it is too large Load Diff