Skip to content

Commit

Permalink
ft(article-readtime): Add article readtime feature (#32)
Browse files Browse the repository at this point in the history
- Add calculate readtime functionality
- Add interprete readtime functionality

[Delivers #165273489]
  • Loading branch information
sanya-kenneth authored and archibishop committed May 9, 2019
1 parent c44d44f commit 6614de1
Show file tree
Hide file tree
Showing 7 changed files with 10,020 additions and 3 deletions.
18 changes: 18 additions & 0 deletions authors/apps/articles/migrations/0005_article_read_time.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.1 on 2019-05-08 18:38

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('articles', '0004_auto_20190508_0526'),
]

operations = [
migrations.AddField(
model_name='article',
name='read_time',
field=models.TextField(default='less than a minute'),
),
]
1 change: 1 addition & 0 deletions authors/apps/articles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Article(models.Model):
report_count = models.IntegerField(default=0)
favorited = models.BooleanField(default=False)
favorite_count = models.IntegerField(default=0)
read_time = models.TextField(default="less than a minute")
tagList = models.ManyToManyField(ArticleTag, related_name='articles')
author = models.ForeignKey(
User, to_field='username', on_delete=models.CASCADE, null=False)
Expand Down
55 changes: 55 additions & 0 deletions authors/apps/articles/readtime_engine.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import re


class ArticleTimeEngine:
"""
Class for estimating the time it takes to
read an article
"""
def __init__(self, article_body):
self.article_body = article_body

def filter_words(self):
"""
Method filters out words from an article body
"""
filtered_words = re.findall(r'\w+', self.article_body)
return filtered_words

def total_word_count(self):
"""
Method returns total number of filtered words
"""
return len(self.filter_words())

def calculate_read_time(self):
"""
Method calculates minutes it takes to read an article
"""
# Average reading time for a normal person in words per minute
WPM = 250
time = self.total_word_count()/WPM
actual_time = round(time)
return actual_time

def read_time(self):
# minutes in an hour
hour = 60
# hours a day
day = 24
# get calculated time
time = self.calculate_read_time()
# check if time is less than a minute
if time < 1:
return "less than a minute read"
# check if time is greater than 1 hour
if time >= hour:
# convert minutes to hours
hours = round(time/hour)
# check if time is greater than a day
if hours >= day:
# convert hours to days
days = round(hours/day)
return f"{days} day read"
return f"{hours} hour read"
return f"{time} minute read"
6 changes: 4 additions & 2 deletions authors/apps/articles/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,13 @@ class Meta:
'favorited',
'favorite_count',
'author',
'tagList', 'social_links',
'tagList',
'read_time',
'social_links',
)
read_only_fields = ('created_at', 'updated_at', 'author',
'favorited', 'favorite_count', 'slug',
'social_links')
'social_links', 'read_time')


class ReportSerializer(serializers.ModelSerializer):
Expand Down
9,884 changes: 9,884 additions & 0 deletions authors/apps/articles/tests/readtime_test_data.py

Large diffs are not rendered by default.

54 changes: 54 additions & 0 deletions authors/apps/articles/tests/test_article_readtime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from django.urls import reverse
from .base import BaseTestCase
from .readtime_test_data import less_than_a_minute, one_hour_read,\
days_read, minutes_read


class ArticleReadTimeTestCase(BaseTestCase):
"""
Class for testing the article read time
"""

def test_api_estimates_articles_of_less_than_a_minute(self):
"""
Method tests if the api returns readtime of less then a minute
"""
url = reverse('articles-list-create')
response = self.client.post(
url, less_than_a_minute, HTTP_AUTHORIZATION=self.auth_header, format="json")
self.assertEqual(response.status_code, 201)
self.assertEqual(
response.data["article"]["read_time"], "less than a minute read")

def test_api_estimates_minute_long_article_read_time(self):
"""
Method tests if the api returns readtime in minutes if the article
takes minutes to read
"""
url = reverse('articles-list-create')
response = self.client.post(
url, minutes_read, HTTP_AUTHORIZATION=self.auth_header, format="json")
self.assertEqual(response.status_code, 201)
self.assertIn("minute read", str(response.data))

def test_api_estimates_hours_long_article_read_time(self):
"""
Method tests if the api returns readtime in hours if the article
takes hours to read
"""
url = reverse('articles-list-create')
response = self.client.post(
url, one_hour_read, HTTP_AUTHORIZATION=self.auth_header, format="json")
self.assertEqual(response.status_code, 201)
self.assertIn("hour read", str(response.data))

def test_api_estimates_days_long_article_read_time(self):
"""
Method tests if api returns readtime in days if the article
takes days to read
"""
url = reverse('articles-list-create')
response = self.client.post(
url, days_read, HTTP_AUTHORIZATION=self.auth_header, format="json")
self.assertEqual(response.status_code, 201)
self.assertIn("day read", str(response.data))
5 changes: 4 additions & 1 deletion authors/apps/articles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .serializers import ArticleSerializer, ReportSerializer
from .permissions import IsOwnerOrReadOnly
from .pagination import ArticlePageNumberPagination
from .readtime_engine import ArticleTimeEngine


class ListArticles(generics.ListAPIView):
Expand Down Expand Up @@ -52,8 +53,10 @@ def create(self, request, **kwargs):
ArticleTagView.create_tag(ArticleTagView, request.data.get("tagList"))
serializer = ArticleSerializer(data=data, context={'request': request})
serializer.is_valid(raise_exception=True)
read_time = ArticleTimeEngine(data['body'])
save_serialiser = serializer.save(
author=self.request.user
author=self.request.user,
read_time = read_time.read_time()
)
for tag in data['tagList']:
save_serialiser.tagList.add(
Expand Down

0 comments on commit 6614de1

Please sign in to comment.