diff --git a/db.sqlite3 b/db.sqlite3 new file mode 100644 index 0000000..8c6b391 Binary files /dev/null and b/db.sqlite3 differ diff --git a/delivery/__init__.py b/delivery/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/delivery/__pycache__/__init__.cpython-311.pyc b/delivery/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..d2a043b Binary files /dev/null and b/delivery/__pycache__/__init__.cpython-311.pyc differ diff --git a/delivery/__pycache__/admin.cpython-311.pyc b/delivery/__pycache__/admin.cpython-311.pyc new file mode 100644 index 0000000..1cb32ee Binary files /dev/null and b/delivery/__pycache__/admin.cpython-311.pyc differ diff --git a/delivery/__pycache__/apps.cpython-311.pyc b/delivery/__pycache__/apps.cpython-311.pyc new file mode 100644 index 0000000..7d9a030 Binary files /dev/null and b/delivery/__pycache__/apps.cpython-311.pyc differ diff --git a/delivery/__pycache__/forms.cpython-311.pyc b/delivery/__pycache__/forms.cpython-311.pyc new file mode 100644 index 0000000..2c780bf Binary files /dev/null and b/delivery/__pycache__/forms.cpython-311.pyc differ diff --git a/delivery/__pycache__/models.cpython-311.pyc b/delivery/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000..9e3f4af Binary files /dev/null and b/delivery/__pycache__/models.cpython-311.pyc differ diff --git a/delivery/__pycache__/urls.cpython-311.pyc b/delivery/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000..cbcf942 Binary files /dev/null and b/delivery/__pycache__/urls.cpython-311.pyc differ diff --git a/delivery/__pycache__/views.cpython-311.pyc b/delivery/__pycache__/views.cpython-311.pyc new file mode 100644 index 0000000..e0e9b7e Binary files /dev/null and b/delivery/__pycache__/views.cpython-311.pyc differ diff --git a/delivery/admin.py b/delivery/admin.py new file mode 100644 index 0000000..dd8f8a0 --- /dev/null +++ b/delivery/admin.py @@ -0,0 +1,16 @@ +from django.contrib import admin + +# Register your models here. + +# allow admin make change in employee table +from .models import employee,deliverym,team,van,emp + +admin.site.register(employee) +admin.site.register(deliverym) +admin.site.register(emp) +admin.site.register(van) +admin.site.register(team) +# class Postuni(admin.ModelAdmin): +# # show field to show to admin +# list_display = ( 'source', 'destination') + \ No newline at end of file diff --git a/delivery/apps.py b/delivery/apps.py new file mode 100644 index 0000000..32f5024 --- /dev/null +++ b/delivery/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class DeliveryConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'delivery' diff --git a/delivery/forms.py b/delivery/forms.py new file mode 100644 index 0000000..639c360 --- /dev/null +++ b/delivery/forms.py @@ -0,0 +1,28 @@ + +from django import forms + + + +# accounts +from django.contrib.auth.forms import UserCreationForm, UserChangeForm +from django.contrib.auth.models import User +from .models import employee,deliverym + +class RegisterForm(forms.ModelForm): + password = forms.CharField(widget=forms.PasswordInput()) + class Meta(): + model = User + fields = ('username','password','email') +class EmpForm(forms.ModelForm): + class Meta: + model = employee + fields = ('phonenumber',) + def clean(self): + cleaned_data = super(EmpForm, self).clean() + +class DeliveryForm(forms.ModelForm): + class Meta: + model = deliverym + fields = ('source','destination','route','delivery_id') + def clean(self): + cleaned_data = super(DeliveryForm, self).clean() \ No newline at end of file diff --git a/delivery/models.py b/delivery/models.py new file mode 100644 index 0000000..de53cb0 --- /dev/null +++ b/delivery/models.py @@ -0,0 +1,56 @@ +# from django.db import models + +# Create your models here. +from django.db import models +from django.contrib.auth.models import User +# users model +class employee(models.Model): + user = models.OneToOneField(User,on_delete=models.CASCADE,related_name='puser') + username = models.CharField(max_length=200) + phonenumber=models.IntegerField() + def __str__(self): + return self.user.username + + +# user +class deliverym(models.Model): + # source = models.ForeignKey(Question, on_delete=models.CASCADE) + delivery_id=models.IntegerField() + source = models.CharField(max_length=200) + destination = models.CharField(max_length=200) + route = models.CharField(max_length=200) + delivery_emp = models.ForeignKey(User, null=True, on_delete=models.CASCADE) + status=models.CharField(max_length=100) + #to convert model's object into string + # def __str__(self): + # return self.delivery_id + + +class emp(models.Model): + emp_id=models.IntegerField() + fname = models.CharField(max_length=200) + lname = models.CharField(max_length=200) + usermode = models.CharField(max_length=200) + phonenumber=models.IntegerField() + email = models.CharField(max_length=20) + username = models.CharField(max_length=200) + password = models.CharField(max_length=200) + # def __str__(self): + # return self.emp.username + +class team(models.Model): + team_id=models.IntegerField() + name = models.CharField(max_length=200) + emp_id = models.ManyToManyField(emp, null=True) + # def __str__(self): + # return self.team.name + + +class van(models.Model): + van_id=models.IntegerField() + license_no = models.CharField(max_length=200) + van_status = models.CharField(max_length=200) + emp_id = models.ForeignKey(emp, null=True, on_delete=models.CASCADE) + team_id=models.ForeignKey(team, null=True, on_delete=models.CASCADE) + # def __str__(self): + # return self.van.username \ No newline at end of file diff --git a/delivery/tests.py b/delivery/tests.py new file mode 100644 index 0000000..de8bdc0 --- /dev/null +++ b/delivery/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/delivery/urls.py b/delivery/urls.py new file mode 100644 index 0000000..848173e --- /dev/null +++ b/delivery/urls.py @@ -0,0 +1,37 @@ +from django.urls import path + +# from . import views +from .views import * + +urlpatterns = [ + path("index", index, name="index"), + path('login/', user_login, name='login'), + # path('registerr/', register, name='registerr'), + + path('delivery_detail/', delivery_detail, name='delivery_detail'), + path('registerr/', register, name='registerr'), + + # path('display_data//deliveries/', display_data, name='display_data'), + # Add more URL patterns here as needed + path('logout/', LogoutView.as_view(), name='logout'), + + + +] + + + +# from django.urls import path + +# from . import views + +# urlpatterns = [ +# # ex: /polls/ +# path("", views.index, name="index"), +# # ex: /polls/5/ +# path("/", views.detail, name="detail"), +# # ex: /polls/5/results/ +# path("/results/", views.results, name="results"), +# # ex: /polls/5/vote/ +# path("/vote/", views.vote, name="vote"), +# ] \ No newline at end of file diff --git a/delivery/views.py b/delivery/views.py new file mode 100644 index 0000000..4abe617 --- /dev/null +++ b/delivery/views.py @@ -0,0 +1,83 @@ +from django.shortcuts import render,redirect +from django.contrib.auth import logout,authenticate,login +from django.urls import reverse +from django.http import HttpResponse, HttpResponseRedirect +from .models import employee,deliverym +from .forms import RegisterForm,EmpForm,DeliveryForm + +# Create your views here. + +def index(request): + return render(request, "base.html") + # return HttpResponse("Hello, world. You're at the delivery index.") + + +def register(request): + registered = False + if request.method == 'POST': + user_form = RegisterForm(data=request.POST) + profile_form = DeliveryForm(data=request.POST) + if user_form.is_valid() and profile_form.is_valid(): + user = user_form.save() + user.set_password(user.password) + user.save() + profile = profile_form.save(commit=False) + profile.user = user + print('account created') + profile.save() + # delivery.save() + registered = True + else: + print(user_form.errors,profile_form.errors) + else: + user_form = RegisterForm() + profile_form = DeliveryForm() + return render(request,'profile.html', + {'user_form':user_form, + 'profile_form':profile_form, + 'registered':registered}) + + +# login function +def user_login(request): + if request.method == 'POST': + username = request.POST.get('username') + password = request.POST.get('password') + user = authenticate(username=username, password=password) + + + if user: + if user.is_active: + login(request,user) + print("hello welcome") + return HttpResponseRedirect(reverse('delivery_detail')) + else: + return HttpResponse("Your account was inactive.") + else: + print("Someone tried to login and failed.") + print("They used username: {} and password: {}".format(username,password)) + return HttpResponseRedirect(reverse('login')) + else: + return render(request, 'loginform.html', {}) + +# from django.http import HttpResponse +from django.template import loader +# from .models import Member + +# from django.http import HttpResponse, HttpResponseRedirect +from django.template import loader +from django.views import View +from django.shortcuts import get_object_or_404 + +def delivery_detail(request): + model=deliverym + delivery_details = deliverym.objects.filter(delivery_emp = request.user) + # delivery_details = deliverym.objects.filter(user=request.employee) + return render(request, 'delivery.html', { 'delivery_details': delivery_details}) + +class LogoutView(View): + def get(self, request, *args, **kwargs): + logout(request) + return redirect('/delivery/login/') + + diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..e398d8f --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/mysite/__init__.py b/mysite/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mysite/__pycache__/__init__.cpython-311.pyc b/mysite/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..7a822ea Binary files /dev/null and b/mysite/__pycache__/__init__.cpython-311.pyc differ diff --git a/mysite/__pycache__/settings.cpython-311.pyc b/mysite/__pycache__/settings.cpython-311.pyc new file mode 100644 index 0000000..eac043c Binary files /dev/null and b/mysite/__pycache__/settings.cpython-311.pyc differ diff --git a/mysite/__pycache__/urls.cpython-311.pyc b/mysite/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000..6c5feca Binary files /dev/null and b/mysite/__pycache__/urls.cpython-311.pyc differ diff --git a/mysite/__pycache__/wsgi.cpython-311.pyc b/mysite/__pycache__/wsgi.cpython-311.pyc new file mode 100644 index 0000000..f82a0b9 Binary files /dev/null and b/mysite/__pycache__/wsgi.cpython-311.pyc differ diff --git a/mysite/asgi.py b/mysite/asgi.py new file mode 100644 index 0000000..6b7e917 --- /dev/null +++ b/mysite/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for mysite project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') + +application = get_asgi_application() diff --git a/mysite/settings.py b/mysite/settings.py new file mode 100644 index 0000000..23540fc --- /dev/null +++ b/mysite/settings.py @@ -0,0 +1,135 @@ +""" +Django settings for mysite project. + +Generated by 'django-admin startproject' using Django 4.2. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.2/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent +import os + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-6&lg$3#lwvhafb3qq=*no_x4&g5+stnezh@i5=y4)e-oradb6l' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + "delivery.apps.DeliveryConfig", + # 'django.contrib.delivery', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'mysite.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, 'templates')], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'mysite.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/4.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/4.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.0/howto/static-files/ + +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, 'static'), +] + diff --git a/mysite/urls.py b/mysite/urls.py new file mode 100644 index 0000000..0660678 --- /dev/null +++ b/mysite/urls.py @@ -0,0 +1,29 @@ +""" +URL configuration for mysite project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +from django.contrib import admin +from django.urls import include, path + +urlpatterns = [ + path("delivery/", include("delivery.urls")), + path("admin/", admin.site.urls), +] \ No newline at end of file diff --git a/mysite/wsgi.py b/mysite/wsgi.py new file mode 100644 index 0000000..af046f8 --- /dev/null +++ b/mysite/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for mysite project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') + +application = get_wsgi_application() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..423225a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,54 @@ +alembic==1.10.3 +asgiref==3.6.0 +async-generator==1.10 +attrs==22.2.0 +backoff==2.2.1 +beautifulsoup4==4.12.2 +branca==0.6.0 +bs4==0.0.1 +certifi==2022.12.7 +cffi==1.15.1 +charset-normalizer==3.1.0 +click==8.1.3 +colorama==0.4.6 +cryptography==40.0.1 +distro==1.8.0 +Django==4.2 +exceptiongroup==1.1.1 +Flask==2.2.3 +Flask-Migrate==4.0.4 +Flask-Simple-GeoIP==0.2.4 +Flask-SQLAlchemy==3.0.3 +folium==0.14.0 +geographiclib==2.0 +geopy==2.3.0 +greenlet==2.0.2 +h11==0.14.0 +idna==3.4 +ipaddress==1.0.23 +itsdangerous==2.1.2 +Jinja2==3.1.2 +Mako==1.2.4 +MarkupSafe==2.1.2 +numpy==1.24.2 +opencage==2.1.0 +outcome==1.2.0 +phonenumbers==8.13.9 +pycparser==2.21 +pyOpenSSL==23.1.1 +PySocks==1.7.1 +requests==2.28.2 +selenium==4.8.3 +simple-geoip==0.1.1 +sniffio==1.3.0 +sortedcontainers==2.4.0 +soupsieve==2.4 +SQLAlchemy==2.0.9 +sqlparse==0.4.3 +trio==0.22.0 +trio-websocket==0.10.2 +typing_extensions==4.5.0 +tzdata==2023.3 +urllib3==1.26.15 +Werkzeug==2.2.3 +wsproto==1.2.0 diff --git a/static/images/log2.jpg b/static/images/log2.jpg new file mode 100644 index 0000000..2c3049e Binary files /dev/null and b/static/images/log2.jpg differ diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..11be4a9 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,32 @@ + + + + + + + + + + {% block title %}Tracking Delivery {% endblock title %} + + {% include 'partials/_styles.html' %} + + + + + + {% include 'partials/_navbar.html' %} +

/n

+ + +
+ +

hello!

+

welcome to delivery tracking website

+ + {% block content %}{% endblock content %} + +
+ + + {% include 'partials/_footer.html' %} \ No newline at end of file diff --git a/templates/delivery.html b/templates/delivery.html new file mode 100644 index 0000000..a29e864 --- /dev/null +++ b/templates/delivery.html @@ -0,0 +1,23 @@ + +{% extends 'base.html' %} +{% block widgets %}{% endblock widgets %} +{% block title %}{{ block.super }}| {{ request.user|title }} Profile{% endblock title %} +{% block content %} +
+

Delivery details

+
    +{% for delivery in delivery_details %} +
  • + Delivery status: {{ delivery.status }}
    + Delivery source: {{ delivery.source }}
    + Delivery destination: {{ delivery.destination }}
    + Delivery route: {{ delivery.route }}
    + + +
  • +{% empty %} +
  • No deliveries found for this employee.
  • +{% endfor %} +
+
+{% endblock content %} \ No newline at end of file diff --git a/templates/form.html b/templates/form.html new file mode 100644 index 0000000..184d617 --- /dev/null +++ b/templates/form.html @@ -0,0 +1,4 @@ +
+

enter IP

+ +
\ No newline at end of file diff --git a/templates/loginform.html b/templates/loginform.html new file mode 100644 index 0000000..152a7a3 --- /dev/null +++ b/templates/loginform.html @@ -0,0 +1,53 @@ + + +{% block widgets %}{% endblock widgets %} +{% block title %}{{ block.super }}| User Login{% endblock title %} +{% block content %} +{% load static %} +
+ +
+
+
+ +
+
+
User Login
+
+ + +
+ {% csrf_token %} + {# A more "HTML" way of creating the login form#} + + + + + + +
+ + +
+
+
+
+
+
+ + + + diff --git a/templates/partials/_footer.html b/templates/partials/_footer.html new file mode 100644 index 0000000..e977eb5 --- /dev/null +++ b/templates/partials/_footer.html @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/templates/partials/_navbar.html b/templates/partials/_navbar.html new file mode 100644 index 0000000..e9cd4e2 --- /dev/null +++ b/templates/partials/_navbar.html @@ -0,0 +1,44 @@ + \ No newline at end of file diff --git a/templates/partials/_styles.html b/templates/partials/_styles.html new file mode 100644 index 0000000..c642a3d --- /dev/null +++ b/templates/partials/_styles.html @@ -0,0 +1,11 @@ +{% load static %} + + + + + + + + \ No newline at end of file diff --git a/templates/profile.html b/templates/profile.html new file mode 100644 index 0000000..f053e13 --- /dev/null +++ b/templates/profile.html @@ -0,0 +1,39 @@ +{% extends 'base.html' %} +{% block widgets %}{% endblock widgets %} +{% block title %}{{ block.super }}| {{ request.user|title }} Profile{% endblock title %} +{% block content %} +
+ +
+
+
+
+

Sign up

+ + +
+
+ {% csrf_token %} + {{ user_form.as_p }} + {{ profile_form.as_p }} + +
+
+
+
+
+{% endblock content %} \ No newline at end of file diff --git a/templates/profileedit.html b/templates/profileedit.html new file mode 100644 index 0000000..2755ad0 --- /dev/null +++ b/templates/profileedit.html @@ -0,0 +1,31 @@ +{% extends 'base.html' %} + +{% block widgets %}{% endblock widgets %} +{% block title %}{{ block.super }}| User Login{% endblock title %} +{% block content %} +{% load static %} + + +
+
+
+ + +
+
+
+ + Sign up + +
+
+
+ {%csrf_token%} + + {{form.as_p}} + +
+
+
+
+{% endblock content %} \ No newline at end of file diff --git a/templates/register.html b/templates/register.html new file mode 100644 index 0000000..d7eb60e --- /dev/null +++ b/templates/register.html @@ -0,0 +1,21 @@ +{% extends 'base.html' %} +{% block widgets %}{% endblock widgets %} +{% block title %}{{ block.super }}| User Registration{% endblock title %} +{% block content %} +
+
+
+
User Registration
+
+
+ {% csrf_token %} + {{ form.as_p }} + + +
+

Already have an account? Login here..

+
+
+
+
+{% endblock content %} \ No newline at end of file diff --git a/templates/signup.html b/templates/signup.html new file mode 100644 index 0000000..c119e73 --- /dev/null +++ b/templates/signup.html @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/templates/trackpage.html b/templates/trackpage.html new file mode 100644 index 0000000..95f598e --- /dev/null +++ b/templates/trackpage.html @@ -0,0 +1,7 @@ +{% extends "index.html" %} +{% block content %} +

Here are your coordiantes

+

longitude : {{longitude}}

+

latitude : {{latitude}}

+

content : {{contentt}}

+{% endblock %} \ No newline at end of file