Added public farm location type

+Added PublicFarm and Resource models
+Farms have resources that they can harvest
+Added commands to add farms and add/remove resources from them
+Added find_farm to find farms
doc_update
Joey Hines 2019-03-02 11:48:28 -06:00
parent 890b78140c
commit f8ae09fd56
14 changed files with 238 additions and 13 deletions

View File

@ -9,3 +9,5 @@ admin.site.register(Tunnel)
admin.site.register(ItemListing) admin.site.register(ItemListing)
admin.site.register(APIToken) admin.site.register(APIToken)
admin.site.register(Town) admin.site.register(Town)
admin.site.register(PublicFarm)
admin.site.register(Resource)

View File

@ -175,6 +175,25 @@ def add_town(x_pos, z_pos, name=None, discord_uuid=None, mc_uuid=None):
return add_location(x_pos, z_pos, name=name, discord_uuid=discord_uuid, mc_uuid=mc_uuid, loc_type=Town) return add_location(x_pos, z_pos, name=name, discord_uuid=discord_uuid, mc_uuid=mc_uuid, loc_type=Town)
@command("POST")
def add_farm(x_pos, z_pos, name=None, discord_uuid=None, mc_uuid=None):
'''
:request: POST
:param x_pos: MC X Coordinate
:param z_pos: MC Z Coordinate
:param name: Shop Name (If None, Defaults to Player's Shop)
:param discord_uuid: Discord UUID
:param mc_uuid: Minecraft UUID
:return: JSON representation of the new town
:raises: EntryNameNotUniqueError, PlayerNotFound, LocationLookupError
:help: Adds your public farm to the database.
'''
return add_location(x_pos, z_pos, name=name, discord_uuid=discord_uuid, mc_uuid=mc_uuid, loc_type=PublicFarm)
@command("POST") @command("POST")
def add_tunnel(tunnel_direction, tunnel_number, location_name=None, discord_uuid=None, mc_uuid=None): def add_tunnel(tunnel_direction, tunnel_number, location_name=None, discord_uuid=None, mc_uuid=None):
''' '''
@ -296,6 +315,36 @@ def add_item(item_name, quantity, diamond_price, shop_name=None, discord_uuid=No
return item_listing.json return item_listing.json
@command("POST")
def add_resource(resource_name, farm_name=None, discord_uuid=None, mc_uuid=None):
'''
:request: POST
:param resource_name: name of the resource
;param farm_name: name of the farm to add the resource to. Can be none.
:param discord_uuid: Discord UUID
:param mc_uuid: Minecraft UUID
:return: Item Listing
:raises: PlayerNotFound, LocationLookupError, EntryNameNotUniqueError, NoLocationsInDatabase
:help: Adds a resource to a farm.
'''
player = get_player(discord_uuid, mc_uuid)
farm = get_location(player, farm_name, PublicFarm).publicfarm
resource = Resource.objects.create(farm=farm, resource_name=resource_name)
return resource.json
@command("GET")
def find_farm(resource_name):
if len(resource_name) == 0:
raise EmptryString
return objects_list_to_json(PublicFarm.objects.filter(resource__resource_name__icontains=resource_name).all())
@command("GET") @command("GET")
def selling(item_name): def selling(item_name):
''' '''
@ -323,7 +372,6 @@ def selling_price(item_name):
def get_selling(item_name, sort): def get_selling(item_name, sort):
items = [] items = []
if len(item_name) == 0: if len(item_name) == 0:
raise EmptryString raise EmptryString
@ -513,6 +561,33 @@ def delete_item(item, shop_name=None, discord_uuid=None, mc_uuid=None):
return shop.json return shop.json
@command("POST")
def delete_resource(resource_name, farm_name=None, discord_uuid=None, mc_uuid=None):
'''
:request: POST
:param resource: resource to delete
:param farm_name: Farm with resource, can be None if the user only has one farm
:param discord_uuid: Discord UUID
:param mc_uuid: Minecraft UUID
:return: PublicFarm where the resource was deleted from
:raises: PlayerNotFound, LocationLookupError, EntryNameNotUniqueError, NoLocationsInDatabase, ItemNotFound
:help: Deletes a resource from a farm
'''
player = get_player(discord_uuid=discord_uuid, mc_uuid=mc_uuid)
farm = get_location(player, farm_name, PublicFarm)
delete_list = Resource.objects.filter(resource_name=resource_name, farm=farm).all()
if len(delete_list) == 0:
raise ResourceNotFoundError
delete_list.delete()
return farm.json
@command("GET") @command("GET")
def me(discord_uuid=None, mc_uuid=None): def me(discord_uuid=None, mc_uuid=None):
''' '''

View File

@ -105,3 +105,7 @@ class ResidentNotFoundError(DataBaseError):
class OwnerNotFoundError(DataBaseError): class OwnerNotFoundError(DataBaseError):
"""No owner matches""" """No owner matches"""
class ResourceNotFoundError(DataBaseError):
"""No resource found"""

View File

@ -0,0 +1,31 @@
# Generated by Django 2.1.2 on 2019-03-01 20:28
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('GeoffreyApp', '0007_town'),
]
operations = [
migrations.CreateModel(
name='PublicFarm',
fields=[
('location_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='GeoffreyApp.Location')),
],
bases=('GeoffreyApp.location',),
),
migrations.CreateModel(
name='Resource',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('resource_name', models.CharField(max_length=128)),
('farm', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='resource',
to='GeoffreyApp.PublicFarm')),
],
),
]

View File

@ -112,10 +112,6 @@ class Location(models.Model):
return owner_list return owner_list
@property
def link(self):
return ""
@property @property
def json(self): def json(self):
return {"type": self.__class__.__name__, return {"type": self.__class__.__name__,
@ -137,7 +133,10 @@ class Location(models.Model):
@property @property
def link(self): def link(self):
return self.loc_child_obj.link child = self.loc_child_obj
if child != self:
return self.loc_child_obj.link
@property @property
def loc_child_obj(self): def loc_child_obj(self):
@ -147,6 +146,8 @@ class Location(models.Model):
return self.base return self.base
elif hasattr(self, "town"): elif hasattr(self, "town"):
return self.town return self.town
elif hasattr(self, "publicfarm"):
return self.publicfarm
else: else:
return self return self
@ -208,6 +209,23 @@ class Town(Location):
return reverse("GeoffreyTownInfo", kwargs={"id": self.id}) return reverse("GeoffreyTownInfo", kwargs={"id": self.id})
class PublicFarm(Location):
@property
def link(self):
return reverse("GeoffreyPublicFarmInfo", kwargs={"id": self.id})
class Resource(models.Model):
farm = models.ForeignKey(PublicFarm, related_name="resource", on_delete=models.CASCADE)
resource_name = models.CharField(max_length=128)
@property
def json(self):
return {"name": self.resource_name,
"farm_id": self.farm_id
}
class ItemListing(models.Model): class ItemListing(models.Model):
item_name = models.CharField(max_length=128) item_name = models.CharField(max_length=128)
''' '''

View File

@ -20,7 +20,7 @@
<td>{{ item.normalized_price }}D</td> <td>{{ item.normalized_price }}D</td>
{% if show_shop %} {% if show_shop %}
<td>{{ item.shop.location }}</td> <td>{{ item.shop.location }}</td>
<td>{% include "GeoffreyApp/location_link.html" with loc=item.shop %}</td> <td><a href="{{ item.shop.link }}">{{ item.shop.name }}</a></td>
{% endif %} {% endif %}
</tr> </tr>
{% endfor %} {% endfor %}

View File

@ -1,5 +0,0 @@
{% if loc.loc_type == "Base" %}
<a href="{% url 'GeoffreyBaseInfo' loc.id %}">{{ loc.name }}</a>
{% elif loc.loc_type == "Shop" %}
<a href="{% url 'GeoffreyShopInfo' loc.id %}">{{ loc.name }}</a>
{% endif %}

View File

@ -0,0 +1,7 @@
{% extends "GeoffreyApp/location.html" %}
{% block info %}
<h2>Resources:</h2>
{% include "GeoffreyApp/resource_table.html" with resource_list=resources %}
<hr class="my-4">
{% endblock %}

View File

@ -0,0 +1,9 @@
{% extends "GeoffreyApp/base.html" %}
{% block header %}
Public Farms
{% endblock %}
{% block content %}
{% include "GeoffreyApp/location_table.html" with loc_list=publicfarm_list show_owner=True %}
{% endblock %}

View File

@ -0,0 +1,20 @@
<table id="resource_table" class="table table-hover link-table">
<thead class="bg-dark">
<tr>
<th>Resource Name</th>
</tr>
</thead>
<tbody>
{% for resource in resource_list %}
<tr>
<td>{{ resource.resource_name }} </td>
</tr>
{% endfor %}
</tbody>
</table>
<script>
$(document).ready(function () {
$('#resource_table').DataTable();
});
</script>

View File

@ -9,7 +9,8 @@ navbar_options = [
("Shops", reverse("GeoffreyShops")), ("Shops", reverse("GeoffreyShops")),
("Bases", reverse("GeoffreyBases")), ("Bases", reverse("GeoffreyBases")),
("Towns", reverse("GeoffreyTowns")), ("Towns", reverse("GeoffreyTowns")),
("Item Listings", reverse("GeoffreyItems")) ("Item Listings", reverse("GeoffreyItems")),
("Public Farms", reverse("GeoffreyPublicFarms"))
] ]
option_format = '<li class="nav-item{}"> <a class="nav-link" href="{}">{} </a> </li>' option_format = '<li class="nav-item{}"> <a class="nav-link" href="{}">{} </a> </li>'

View File

@ -22,6 +22,7 @@ class CommandsAPITestCase(TestCase):
Shop.objects.all().delete() Shop.objects.all().delete()
ItemListing.objects.all().delete() ItemListing.objects.all().delete()
Tunnel.objects.all().delete() Tunnel.objects.all().delete()
PublicFarm.objects.all().delete()
def populate(self): def populate(self):
self.base = Base.objects.create(name="test", x_coord=0, z_coord=0, dimension="O") self.base = Base.objects.create(name="test", x_coord=0, z_coord=0, dimension="O")
@ -38,6 +39,9 @@ class CommandsAPITestCase(TestCase):
self.tunnel = Tunnel.objects.create(tunnel_number="42", tunnel_direction="S", location=self.base) self.tunnel = Tunnel.objects.create(tunnel_number="42", tunnel_direction="S", location=self.base)
self.farm = PublicFarm.objects.create(name="test farm", x_coord=0, z_coord=0, dimension="O")
self.farm.owner.add(self.player)
def test_register(self): def test_register(self):
register(player_name="Vakky", discord_uuid="229423434256351233") register(player_name="Vakky", discord_uuid="229423434256351233")
@ -208,3 +212,35 @@ class CommandsAPITestCase(TestCase):
self.assertRaises(ResidentNotFoundError, remove_resident, new_resident.name, self.town.name, self.assertRaises(ResidentNotFoundError, remove_resident, new_resident.name, self.town.name,
discord_uuid=DISCORD_UUID) discord_uuid=DISCORD_UUID)
def test_add_resource(self):
self.populate()
resource = add_resource(resource_name="sed", farm_name="test farm", discord_uuid=DISCORD_UUID)
farm = PublicFarm.objects.filter(resource__resource_name__icontains="sed").first()
self.assertEqual(resource["farm_id"], farm.id)
def test_remove_resource(self):
self.populate()
resource = add_resource(resource_name="sed", farm_name="test farm", discord_uuid=DISCORD_UUID)
delete_resource(resource_name="sed", farm_name="test farm", discord_uuid=DISCORD_UUID)
farm = PublicFarm.objects.filter(resource__resource_name__icontains="sed").all()
self.assertEqual(len(farm), 0)
def test_find_farm(self):
self.populate()
add_resource(resource_name="sed", farm_name="test farm", discord_uuid=DISCORD_UUID)
list = find_farm(resource_name="sed")
for farm in list:
if farm["name"] == "test farm":
return
self.fail("Farm not found")

View File

@ -13,5 +13,7 @@ urlpatterns = [
url(r'^towns/(?P<id>[0-9]{1,9})/$', views.TownInfo.as_view(), name='GeoffreyTownInfo'), url(r'^towns/(?P<id>[0-9]{1,9})/$', views.TownInfo.as_view(), name='GeoffreyTownInfo'),
url(r'^items/$', views.ItemListingList.as_view(), name='GeoffreyItems'), url(r'^items/$', views.ItemListingList.as_view(), name='GeoffreyItems'),
url(r'^search/$', views.SearchList.as_view(), name='GeoffreySearch'), url(r'^search/$', views.SearchList.as_view(), name='GeoffreySearch'),
url(r'^farm/$', views.PublicFarmList.as_view(), name='GeoffreyPublicFarms'),
url(r'^farm/(?P<id>[0-9]{1,9})/$', views.PublicFarmInfo.as_view(), name='GeoffreyPublicFarmInfo')
] ]

View File

@ -81,6 +81,15 @@ class TownList(generic.ListView):
return context return context
class PublicFarmList(generic.ListView):
model = PublicFarm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['current_page'] = "Public Farms"
return context
class ItemListingList(generic.ListView): class ItemListingList(generic.ListView):
model = ItemListing model = ItemListing
@ -147,3 +156,19 @@ class TownInfo(View):
return render(request, 'GeoffreyApp/town.html', context=context) return render(request, 'GeoffreyApp/town.html', context=context)
except Player.DoesNotExist: except Player.DoesNotExist:
return render(request, 'GeoffreyApp/error.html') return render(request, 'GeoffreyApp/error.html')
class PublicFarmInfo(View):
def get(self, request, id):
try:
public_farm = PublicFarm.objects.get(pk=id)
resources = public_farm.resource.all()
context = {
"loc": public_farm,
"resources": resources
}
return render(request, 'GeoffreyApp/publicfarm.html', context=context)
except Player.DoesNotExist:
return render(request, 'GeoffreyApp/error.html')