страничка рейтинга оконных профилей
This commit is contained in:
@@ -9,8 +9,8 @@ import math
|
||||
def safe_html_spec_symbols(s: str) -> str:
|
||||
""" Очистка строки от HTML-разметки типографа
|
||||
|
||||
:param s: строка которую надо очистить
|
||||
:return: str:
|
||||
:param s: str -- строка которую надо очистить
|
||||
:return: str: str -- очищенная строка
|
||||
"""
|
||||
# очистка строки от некоторых спец-символов HTML
|
||||
result = s.replace('­', '')
|
||||
@@ -40,50 +40,60 @@ def safe_html_spec_symbols(s: str) -> str:
|
||||
# ), "ru", reversed=True).replace(u" ", u"-").replace(u"'", u"").replace(u"/", u"~").replace(u"\\", u"~").replace(u"--", u"-")
|
||||
|
||||
|
||||
def Rus2Url (RusString):
|
||||
return re.sub(r'^-|-$', '',
|
||||
re.sub(r'-{1,}', '-',
|
||||
re.sub(r'<[\s\S]*?>|&[\S]*?;|[\W]', '-',
|
||||
re.sub(r'\+', '-plus', translit(RusString, "ru", reversed=True))
|
||||
)
|
||||
)
|
||||
).lower()
|
||||
# def Rus2Url (RusString):
|
||||
# return re.sub(r'^-|-$', '',
|
||||
# re.sub(r'-{1,}', '-',
|
||||
# re.sub(r'<[\s\S]*?>|&[\S]*?;|[\W]', '-',
|
||||
# re.sub(r'\+', '-plus', translit(RusString, "ru", reversed=True))
|
||||
# )
|
||||
# )
|
||||
# ).lower()
|
||||
#
|
||||
#
|
||||
# # Суммирует все цифры в строке через произвольные (не цифровые) разделители
|
||||
# def SummThrought(StringWSlash):
|
||||
# StringWSlash = re.sub( r"[^0-9]", u",", StringWSlash)
|
||||
# ListTerms = StringWSlash.split(u',')
|
||||
# Summ = 0
|
||||
# for Count in ListTerms:
|
||||
# try:
|
||||
# Summ += int(Count)
|
||||
# except:
|
||||
# pass
|
||||
# return Summ
|
||||
#
|
||||
#
|
||||
def get_rating_set_for_stars(rating: float = 0.) -> list:
|
||||
""" Возвращает массив 1 и 0 для отрисовки звёздочек.
|
||||
|
||||
|
||||
# Суммирует все цифры в строке через произвольные (не цифровые) разделители
|
||||
def SummThrought(StringWSlash):
|
||||
StringWSlash = re.sub( r"[^0-9]", u",", StringWSlash)
|
||||
ListTerms = StringWSlash.split(u',')
|
||||
Summ = 0
|
||||
for Count in ListTerms:
|
||||
try:
|
||||
Summ += int(Count)
|
||||
except:
|
||||
pass
|
||||
return Summ
|
||||
|
||||
|
||||
# возвращает массив 1 и 0 для отрисовки зввездочек.
|
||||
def GetRatingSet4Star ( fRating ):
|
||||
:param rating: float -- рейтинг
|
||||
:return: list: list -- массив 1 и 0 для отрисовки звёздочек
|
||||
"""
|
||||
# if fRating < 0.01:
|
||||
# return []
|
||||
RatingSet = []
|
||||
rating_set = []
|
||||
for CountStar in range(RARING_STAR):
|
||||
if RARING_SET_MIN+CountStar*(RARING_SET_MAX-RARING_SET_MIN)/RARING_STAR+1 <= fRating:
|
||||
RatingSet.append(1)
|
||||
if RARING_SET_MIN+CountStar * (RARING_SET_MAX - RARING_SET_MIN) / RARING_STAR + 1. <= rating:
|
||||
rating_set.append(1)
|
||||
else:
|
||||
RatingSet.append(0)
|
||||
return RatingSet
|
||||
rating_set.append(0)
|
||||
return rating_set
|
||||
#
|
||||
#
|
||||
# # рассчитывает дистанцию в км. между двумя геокоординатами
|
||||
# def GetGeoDistance(lon1, lat1, lat2, lon2):
|
||||
# lonA, latA, latB, lonB = map(math.radians, [lon1, lat1, lat2, lon2])
|
||||
# distance = 2 * math.asin(math.sqrt(math.sin((latB - latA) / 2) ** 2 + math.cos(latA) * math.cos(latB) * math.sin(
|
||||
# (lonB - lonA) / 2) ** 2)) * 6371.032 # РАДИУС ЗЕМЛИ 6371.032 КМ.
|
||||
# return distance
|
||||
|
||||
|
||||
# рассчитывает дистанцию в км. между двумя геокоординатами
|
||||
def GetGeoDistance(lon1, lat1, lat2, lon2):
|
||||
lonA, latA, latB, lonB = map(math.radians, [lon1, lat1, lat2, lon2])
|
||||
distance = 2 * math.asin(math.sqrt(math.sin((latB - latA) / 2) ** 2 + math.cos(latA) * math.cos(latB) * math.sin(
|
||||
(lonB - lonA) / 2) ** 2)) * 6371.032 # РАДИУС ЗЕМЛИ 6371.032 КМ.
|
||||
return distance
|
||||
def normalize(val: float, val_max: float = 5., val_min: float = 0.) -> float:
|
||||
""" Нормализация значения
|
||||
|
||||
|
||||
# нормализация
|
||||
def Normalize(Val, ValMax=5, ValMin=0):
|
||||
return float(Val-ValMin)/float(ValMax-ValMin)
|
||||
:param val: float -- значение которое надо нормализовать
|
||||
:param val_max: float -- максимальное значение в нормализуемом диапазоне
|
||||
:param val_min: float -- минимальное значение в нормализуемом диапазоне
|
||||
:return: float: float -- нормализованное значение
|
||||
"""
|
||||
return float(val - val_min) / float(val_max - val_min)
|
||||
|
||||
90
oknardia/web/report2.py
Normal file
90
oknardia/web/report2.py
Normal file
@@ -0,0 +1,90 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# __author__ = 'Sergei Erjemin'
|
||||
from django.shortcuts import render, redirect
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from oknardia.models import PVCprofiles
|
||||
from oknardia.settings import *
|
||||
from web.add_func import normalize, get_rating_set_for_stars
|
||||
from time import time
|
||||
import json
|
||||
import pytils
|
||||
|
||||
|
||||
def ratings(request: HttpRequest) -> HttpResponse:
|
||||
""" Страница "Рейтинги" в главном меню
|
||||
|
||||
Т.к. пока есть данные и рейтинги только профилей, то делаем редирект на неё
|
||||
|
||||
:param request: HttpRequest -- входящий http-запрос
|
||||
:return: HttpResponse -- исходящий http-ответ
|
||||
"""
|
||||
return redirect('/stat/rating/profiles_rank/')
|
||||
|
||||
|
||||
def profiles_rating(request: HttpRequest) -> HttpResponse:
|
||||
""" Формирует таблицу с рейтингами оконных профилей
|
||||
|
||||
:param request: HttpRequest -- входящий http-запрос
|
||||
:return: HttpResponse -- исходящий http-ответ
|
||||
"""
|
||||
time_start = time()
|
||||
template = "rating/profiles_rating.html"
|
||||
to_template = {}
|
||||
q = PVCprofiles.objects.order_by("fProfileRating", "fProfileSeals", "fProfileHeatTransf",
|
||||
"fProfileSoundproofing", "iProfileHeight", "iProfileRabbet",
|
||||
"iProfileGlazingThickness", "iProfileThickness", "iProfileCameras")
|
||||
table = []
|
||||
keys = [RANK_PVCP_HEAT_TRANSFER_NAME, RANK_PVCP_SOUNDPROOFING_NAME, RANK_PVCP_SEALS_NAME,
|
||||
RANK_PVCP_HEIGHT_NAME, RANK_PVCP_G_THICKNESS_NAME, RANK_PVCP_THICKNESS_NAME,
|
||||
RANK_PVCP_RABBET_NAME, RANK_PVCP_CAMERAS_NUM_NAME, RANK_PVCP_CAMERAS_POPULARITY_NAME]
|
||||
to_template.update({'KEYS': keys})
|
||||
for i in q:
|
||||
try:
|
||||
received_json = json.loads(i.sProfileDescription)
|
||||
except json.decoder.JSONDecodeError:
|
||||
continue
|
||||
if KEY_RATING in received_json:
|
||||
rating_real = True
|
||||
r = received_json[KEY_RATING]
|
||||
color = int(255 - normalize(i.fProfileRating) * 255)
|
||||
rating_color = f"{color},255,{color}"
|
||||
rating_color2 = False
|
||||
elif KEY_RATING_VIRTUAL in received_json:
|
||||
rating_real = False
|
||||
r = received_json[KEY_RATING_VIRTUAL]
|
||||
color = int(255 - normalize(i.fProfileRating) * 64)
|
||||
color2 = int(220 - normalize(i.fProfileRating) * 127)
|
||||
rating_color = f"{color},{color},{color}"
|
||||
rating_color2 = f"{color2},{color2},{color2}"
|
||||
else:
|
||||
continue
|
||||
# if keys == []:
|
||||
# keys = sorted(r.keys())
|
||||
# to_template.update({'KEYS': keys})
|
||||
k_arr = []
|
||||
for j in keys:
|
||||
if rating_real: # Это рейтинг на профили, по которым есть ценник (зелененький)
|
||||
clr = int(255 - r[j] * 255)
|
||||
k_arr.append({"COLOR": f"{clr},255,{clr}", "VAL": r[j], "KEY": j})
|
||||
else: # Это "потенциальный" рейтинг, без реальных ценовых предложений (серенький)
|
||||
clr = int(255 - r[j] * 64)
|
||||
k_arr.append({"COLOR": f"{clr},{clr},{clr}", "VAL": r[j], "KEY": j})
|
||||
table.append({
|
||||
"ID": i.id,
|
||||
"R_REAL": rating_real,
|
||||
"BRAND": i.sProfileManufacturer,
|
||||
"BRAND_URL": pytils.translit.slugify(i.sProfileManufacturer),
|
||||
"NAME": i.sProfileName,
|
||||
"NAME_URL": pytils.translit.slugify(i.sProfileName),
|
||||
"K_ARR": k_arr,
|
||||
"RATING_STAR": get_rating_set_for_stars(i.fProfileRating),
|
||||
"RATING_N": i.fProfileRating,
|
||||
"RATING_COLOR": rating_color,
|
||||
"RATING_COLOR2": rating_color2
|
||||
})
|
||||
|
||||
# получаем данные для фрейма ценовых предложений
|
||||
to_template.update({'TABLE': table})
|
||||
to_template.update({'ticks': float(time() - time_start)})
|
||||
response = render(request, template, to_template)
|
||||
return response
|
||||
Reference in New Issue
Block a user