Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
240 changes: 219 additions & 21 deletions LICENSE

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Abans d’enviar, assegura’t de seguir l’estil de codi del projecte i escriu

## ✉️ Contacte
Per dubtes tècnics o col·laboració, contacta amb el desenvolupador principal:
📧 a.moreno@estudiantat.upc.edu
📧 anyer.moreno@estudiantat.upc.edu

## 📄 Llicència
Aquest projecte està llicenciat sota la MIT License – consulta el fitxer LICENSE per a més informació.
This project is licensed under the terms of the GNU General Public License v3.0 – see the LICENSE file for details.
Empty file added app/management/__init__.py
Empty file.
Empty file.
184 changes: 184 additions & 0 deletions app/management/commands/create_basic_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import random
from datetime import timedelta

from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from django.utils import timezone

from app.models import App
from app.services import AppService
from metric.constants import MetricCode
from metric.models import Metric, MetricValue
from source.models import Source


class Command(BaseCommand):
help = "Crea les Sources i Metric bàsiques"

def handle(self, *args, **kwargs):
average_rating = Metric.objects.create(
code="average_rating",
name="Average Rating",
value_type="float",
description="Valoració mitjana de l'app",
)
total_reviews = Metric.objects.create(
code="total_reviews",
name="Total Reviews",
value_type="integer",
description="Nombre total de ressenyes",
)
daily_news_blog_mentions = Metric.objects.create(
code="daily_news_blog_mentions",
name="Daily News Blog Mentions",
value_type="integer",
description="Nombre de mencions diàries a blogs de notícies",
)
daily_social_network_mentions = Metric.objects.create(
code="daily_social_network_mentions",
name="Daily Social Network Mentions",
value_type="integer",
description="Nombre de mencions diàries a Reddit",
)
total_downloads = Metric.objects.create(
code="total_downloads",
name="Total Downloads",
value_type="integer",
description="Número de descàrregues de l'app",
)
last_update_date = Metric.objects.create(
code="last_update_date",
name="Last Update Date",
value_type="date",
description="Data de la darrera actualització.",
)
Metric.objects.create(
code="bug_rate",
name="Bug Rate",
value_type="float",
description="Proporció de reviews que mencionen errors"
" o bugs respecte al total de reviews.",
is_derived=True,
)
Metric.objects.create(
code="positive_rate",
name="Positive Rate",
value_type="float",
description="Proporció de reviews amb sentiment positiu respecte al total de reviews.",
is_derived=True,
)
Metric.objects.create(
code="update_changed",
name="Update Changed",
value_type="integer",
description="Indica si la data de darrera actualització ha "
"canviat respecte al dia anterior."
"\nEl valor és 1 si hi ha un canvi i 0 si es manté igual.",
id_derived=True,
)
Source.objects.create(
code="itunes",
name="App Store",
type="api",
url="https://itunes.apple.com",
).metrics.set([average_rating, total_reviews])
Source.objects.create(
code="google_play",
name="Google Play Scraper",
type="scraper",
url="https://play.google.com",
).metrics.set([average_rating, total_reviews, total_downloads, last_update_date])
Source.objects.create(
code="news",
name="News API",
type="api",
url="https://newsapi.org/v2",
).metrics.set([daily_news_blog_mentions])
Source.objects.create(
code="reddit",
name="Reddit API",
type="api",
).metrics.set([daily_social_network_mentions])

user = User.objects.create_superuser(
username="Anyer", email="anyer@example.com", password="Anyer123"
)

service = AppService()

validated_data = {
"code": "discord",
"name": "Discord",
"description": "Discord is designed for gaming and great for just "
"chilling with friends or building a community.",
"appstore_id": "985746746",
"playstore_id": "com.discord",
}
service.create_app(validated_data, user)

validated_data = {
"code": "gemini",
"name": "Google Gemini",
"description": "La aplicación de Google Gemini es un asistente de"
" IA que puede ayudarte a dar rienda suelta a tu creatividad y productividad.",
"appstore_id": "6477489729",
"playstore_id": "com.google.android.apps.bard",
}
service.create_app(validated_data, user)

validated_data = {
"code": "instagram",
"name": "Instagram",
"description": "Aplicació per a socialitzar i compartir fotos i vídeos.",
"appstore_id": "389801252",
"playstore_id": "bla",
}
service.create_app(validated_data, user)

apps = App.objects.all()
metrics = Metric.objects.all()

if not apps.exists() or not metrics.exists():
self.stdout.write(self.style.ERROR("Debes tener apps y métricas creadas"))
return

created_count = 0

for app in apps:
for metric in metrics:
for source in metric.sources.all():
for days_ago in range(45): # últimos 30 días
date = timezone.now() - timedelta(days=days_ago)
if metric.code == MetricCode.AVERAGE_RATING:
value = round(random.uniform(4.4, 4.5), 5)
elif metric.code == MetricCode.TOTAL_REVIEWS:
value = str(random.randint(3050000, 3080000))
elif metric.code == MetricCode.DAILY_NEWS_BLOG_MENTIONS:
value = str(random.randint(0, 5))
elif metric.code == MetricCode.DAILY_SOCIAL_NETWORK_MENTIONS:
value = str(random.randint(150, 300))
elif metric.code == MetricCode.LAST_UPDATE_DATE:
if days_ago < 15:
value = date.date() - timedelta(days=10)
elif days_ago < 30:
value = date.date() - timedelta(days=20)
else:
value = date.date()
else:
value = str(random.randint(500000000, 600000000))

MetricValue.objects.create(
app=app,
metric=metric,
source=source,
value=str(value),
retrieved_at=date,
)
created_count += 1

self.stdout.write(
self.style.SUCCESS(
f"✔ {created_count} MetricValues creados correctamente."
f"✔ Valors per defecte de Source i Metrics creats correctement."
)
)
49 changes: 33 additions & 16 deletions app/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
# Generated by Django 5.1.7 on 2025-03-31 18:07
# Generated by Django 5.1.7 on 2025-05-30 17:42

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = []
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
Expand All @@ -16,28 +20,41 @@ class Migration(migrations.Migration):
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("code", models.CharField(max_length=100)),
("name", models.CharField(max_length=200)),
("description", models.TextField()),
(
"appstore_id",
models.CharField(max_length=100, null=True, unique=True),
),
(
"playstore_id",
models.CharField(max_length=100, null=True, unique=True),
),
("developer", models.CharField(max_length=100, null=True, unique=True)),
("description", models.TextField(blank=True, null=True)),
("appstore_id", models.CharField(max_length=100, null=True)),
("playstore_id", models.CharField(max_length=100, null=True)),
("developer", models.CharField(max_length=100, null=True)),
("available_on_ios", models.BooleanField(default=False)),
("available_on_android", models.BooleanField(default=False)),
("pegi_rating", models.CharField(max_length=10, null=True)),
("release_date", models.DateField(null=True)),
("min_ios_version", models.CharField(max_length=10, null=True)),
("icon_url", models.URLField(null=True)),
("size_in_bytes", models.BigIntegerField(null=True)),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="apps",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"constraints": [
models.UniqueConstraint(fields=("user", "code"), name="unique_user_code"),
models.UniqueConstraint(
fields=("user", "appstore_id"), name="unique_user_appstore_id"
),
models.UniqueConstraint(
fields=("user", "playstore_id"), name="unique_user_playstore_id"
),
],
},
),
]
19 changes: 0 additions & 19 deletions app/migrations/0002_app_code.py

This file was deleted.

18 changes: 0 additions & 18 deletions app/migrations/0003_alter_app_developer.py

This file was deleted.

23 changes: 0 additions & 23 deletions app/migrations/0004_app_icon_url_app_size_in_bytes.py

This file was deleted.

This file was deleted.

Loading