Fakultas Ilmu Komputer UI

Commit 5b62333e authored by Reyhan Alhafizal Hamidi's avatar Reyhan Alhafizal Hamidi
Browse files

Merge branch '1706040082-55' into 'master'

[#55] Homepage: Hottest Material List

Closes #55

See merge request !103
parents 8d5a308e ee80a2d7
Pipeline #60145 passed with stages
in 32 minutes and 56 seconds
import random import random
import datetime import datetime
import math
from django.contrib.postgres import search from django.contrib.postgres import search
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
...@@ -135,6 +136,25 @@ class Materi(SoftDeleteModel): ...@@ -135,6 +136,25 @@ class Materi(SoftDeleteModel):
count = Review.objects.filter(materi=self).count() count = Review.objects.filter(materi=self).count()
return count return count
@staticmethod
def earliest_materi_timestamp():
return Materi.objects.earliest('date_created').date_created.timestamp()
@property
def seconds_since_earliest_materi(self):
return self.date_created.timestamp() - Materi.earliest_materi_timestamp()
@property
def view_count(self):
count = ViewStatistics.objects.filter(materi=self).count()
return count
@property
def hot_score(self):
view_score = math.log(max(self.view_count, 1), 10)
time_score = self.seconds_since_earliest_materi / 604800 # 1 week
return round(view_score + time_score, 7)
@property @property
def is_like(self): def is_like(self):
like = False like = False
......
...@@ -63,6 +63,9 @@ class DafterKatalogService: ...@@ -63,6 +63,9 @@ class DafterKatalogService:
lst_materi = lst_materi.order_by('date_created') lst_materi = lst_materi.order_by('date_created')
elif (get_sort == "terpopuler"): elif (get_sort == "terpopuler"):
lst_materi = lst_materi.annotate(count=Count('like__id')).order_by('-count') lst_materi = lst_materi.annotate(count=Count('like__id')).order_by('-count')
elif (get_sort == "terhangat"):
lst_materi = sorted(lst_materi,
key=lambda t: (t.hot_score, t.date_created), reverse=True)
elif (get_sort == "jumlah_unduh"): elif (get_sort == "jumlah_unduh"):
lst_materi = lst_materi.annotate(count=Count('unduh__id')).order_by('-count') lst_materi = lst_materi.annotate(count=Count('unduh__id')).order_by('-count')
elif (get_sort == "jumlah_tampilan"): elif (get_sort == "jumlah_tampilan"):
......
...@@ -135,6 +135,9 @@ ...@@ -135,6 +135,9 @@
<li> <li>
<a href="?sort=terpopuler">terpopuler</a> <a href="?sort=terpopuler">terpopuler</a>
</li> </li>
<li>
<a href="?sort=terhangat">terhangat</a>
</li>
<li> <li>
<a href="?sort=judul">judul</a> <a href="?sort=judul">judul</a>
</li> </li>
......
...@@ -6,6 +6,8 @@ import random ...@@ -6,6 +6,8 @@ import random
import re import re
import tempfile import tempfile
import time import time
import itertools
from django.test import override_settings
from datetime import datetime from datetime import datetime
from io import StringIO from io import StringIO
from time import sleep from time import sleep
...@@ -27,6 +29,7 @@ from django.core.files import File ...@@ -27,6 +29,7 @@ from django.core.files import File
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.management import call_command from django.core.management import call_command
from django.db.utils import IntegrityError from django.db.utils import IntegrityError
from pytz import timezone, UTC
from django.test import (Client, RequestFactory, TestCase, TransactionTestCase, from django.test import (Client, RequestFactory, TestCase, TransactionTestCase,
override_settings) override_settings)
from django.urls import resolve, reverse from django.urls import resolve, reverse
...@@ -207,6 +210,163 @@ class DaftarKatalogSortingByJumlahTampilanTest(TestCase): ...@@ -207,6 +210,163 @@ class DaftarKatalogSortingByJumlahTampilanTest(TestCase):
response = self.client.get("/?sort=jumlah_tampilan") response = self.client.get("/?sort=jumlah_tampilan")
self.assertRegex(str(response.content), rf'.*Materi 2.*Materi 1.*') self.assertRegex(str(response.content), rf'.*Materi 2.*Materi 1.*')
class DaftarKatalogSortingByTerhangatTest(TestCase):
@classmethod
def generate_view_materi(cls, materi, view_count):
for _ in itertools.repeat(None, view_count):
ViewStatistics.objects.create(materi=materi)
def get_displayed_materi_in_number(self):
response = self.client.get("/?sort=terhangat")
lst = [int(id) for id in re.findall(r"Materi\s(\d+)[^\d]",
response.content.decode())]
return lst
def setUp(self):
self.contributor_credential = {
"email": "kontributor@gov.id",
"password": id_generator()
}
self.contributor = get_user_model().objects.create_user(
name="Kontributor",
is_contributor=True,
**self.contributor_credential,
)
self.client = Client()
content = b"Test file"
self.cover = SimpleUploadedFile(
"cover.jpg",
content
)
self.content = SimpleUploadedFile(
"content.txt",
content
)
self.materi_data = {
"author": "Reyhan",
"uploader": self.contributor,
"publisher": "Publisher",
"descriptions": "Deskripsi Materi",
"status": "APPROVE",
"cover": self.cover,
"content": self.content,
}
def test_1_week_difference_give_1_hot_score_difference(self):
materi1 = Materi.objects.create(
title='Materi 1',
date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
materi2 = Materi.objects.create(
title='Materi 2',
date_created=datetime(2020, 10, 8, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
materi3 = Materi.objects.create(
title='Materi 3',
date_created=datetime(2020, 10, 15, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
self.generate_view_materi(materi1, 1)
self.generate_view_materi(materi2, 1)
self.generate_view_materi(materi3, 1)
self.assertAlmostEqual(materi3.hot_score - materi2.hot_score, 1)
self.assertAlmostEqual(materi2.hot_score - materi1.hot_score, 1)
def test_10_exponential_view_count_difference_give_1_hot_score_difference(self):
materi1 = Materi.objects.create(
title='Materi 1',
date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
materi2 = Materi.objects.create(
title='Materi 2',
date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
materi3 = Materi.objects.create(
title='Materi 3',
date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
self.generate_view_materi(materi1, 1)
self.generate_view_materi(materi2, 10)
self.generate_view_materi(materi3, 100)
self.assertAlmostEqual(materi3.hot_score - materi2.hot_score, 1)
self.assertAlmostEqual(materi2.hot_score - materi1.hot_score, 1)
def test_0_and_1_views_has_the_same_hot_score(self):
materi1 = Materi.objects.create(
title='Materi 1',
date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
materi2 = Materi.objects.create(
title='Materi 2',
date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
self.generate_view_materi(materi1, 0)
self.generate_view_materi(materi2, 1)
self.assertAlmostEqual(materi1.hot_score, materi2.hot_score)
def test_page_has_option_sort_by_hottest(self):
response = self.client.get("/")
self.assertIn("terhangat", response.content.decode())
def test_page_display_sort_by_hottest(self):
materi1 = Materi.objects.create(
title='Materi 1',
date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
materi2 = Materi.objects.create(
title='Materi 2',
date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
materi3 = Materi.objects.create(
title='Materi 3',
date_created=datetime(2020, 10, 8, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
materi4 = Materi.objects.create(
title='Materi 4',
date_created=datetime(2020, 10, 9, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
self.generate_view_materi(materi1, 11)
self.generate_view_materi(materi2, 10)
self.generate_view_materi(materi3, 1)
self.generate_view_materi(materi4, 1)
lst = self.get_displayed_materi_in_number()
self.assertEqual(lst, [4, 1, 3, 2])
def test_prefer_newest_materi_if_hot_score_is_same(self):
materi1 = Materi.objects.create(
title='Materi 1',
date_created=datetime(2020, 10, 1, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
materi2 = Materi.objects.create(
title='Materi 2',
date_created=datetime(2020, 10, 8, 7, 0, 0, tzinfo=UTC),
**self.materi_data
)
self.generate_view_materi(materi1, 10)
self.generate_view_materi(materi2, 1)
lst = self.get_displayed_materi_in_number()
self.assertEqual(lst, [2, 1])
class DaftarKatalogSortingByJumlahKomentarTest(TestCase): class DaftarKatalogSortingByJumlahKomentarTest(TestCase):
def setUp(self): def setUp(self):
self.client = Client() self.client = Client()
...@@ -3470,7 +3630,7 @@ class MateriRecommendationTest(TestCase): ...@@ -3470,7 +3630,7 @@ class MateriRecommendationTest(TestCase):
response = Client().get("/?recommendation=1") response = Client().get("/?recommendation=1")
list = [int(id) for id in re.findall(r"Materi\s(\d+)[^\d]", response.content.decode())] list = [int(id) for id in re.findall(r"Materi\s(\d+)[^\d]", response.content.decode())]
self.assertEqual(list, [1, 2]) self.assertEqual(list, [1, 2])
class BacaNantiTest(TestCase): class BacaNantiTest(TestCase):
def setUp(self): def setUp(self):
self.contributor_credential = { self.contributor_credential = {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment