Add unittests for contrib/chargen and custom_gametime. Removed unused time units settings from custom_gametime.

This commit is contained in:
Griatch 2017-02-19 13:10:17 +01:00
parent 7e395ea7ec
commit 46a5a62d2b
4 changed files with 137 additions and 96 deletions

View file

@ -2,32 +2,25 @@
Contribution - Griatch 2011
[Note - with the advent of MULTISESSION_MODE=2, this is not really as
> Note - with the advent of MULTISESSION_MODE=2, this is not really as
necessary anymore - the ooclook and @charcreate commands in that mode
replaces this module with better functionality.]
replaces this module with better functionality. This remains here for
inspiration.
This is a simple character creation commandset. A suggestion is to
test this together with menu_login, which doesn't create a Character
on its own. This shows some more info and gives the Player the option
to create a character without any more customizations than their name
(further options are unique for each game anyway).
This is a simple character creation commandset for the Player level.
It shows some more info and gives the Player the option to create a
character without any more customizations than their name (further
options are unique for each game anyway).
Since this extends the OOC cmdset, logging in from the menu will
automatically drop the Player into this cmdset unless they logged off
while puppeting a Character already before.
In MULTISESSION_MODEs 0 and 1, you will automatically log into an
existing Character. When using `@ooc` you will then end up in this
cmdset.
Installation:
Read the instructions in contrib/examples/cmdset.py in order to create
a new default cmdset module for Evennia to use (copy the template up
one level, and change the settings file's relevant variables to point
to the cmdsets inside). If you already have such a module you should
of course use that.
Next import this module in your custom cmdset module and add the
following line to the end of OOCCmdSet's at_cmdset_creation():
self.add(chargen.OOCCmdSetCharGen)
Import this module to `mygame/commands/default_cmdsets.py` and
add `chargen.OOCCMdSetCharGen` to the `PlayerCmdSet` class
(it says where to add it). Reload.
"""
@ -179,7 +172,7 @@ class CmdOOCCharacterCreate(Command):
else:
avail_chars = [new_character.id]
self.caller.db._character_dbrefs = avail_chars
self.caller.msg("|gThe Character |c%s|g was successfully created!" % charname)
self.caller.msg("|gThe character |c%s|g was successfully created!" % charname)
class OOCCmdSetCharGen(default_cmds.PlayerCmdSet):

View file

@ -12,14 +12,23 @@ Usage:
Use as the normal gametime module, that is by importing and using the
helper functions in this module in your own code. The calendar can be
specified in your settings file by adding and setting custom values
for one or more of the variables `TIME_SECS_PER_MIN`,
`TIME_MINS_PER_HOUR`, `TIME_DAYS_PER_WEEK`, `TIME_WEEKS_PER_MONTH` and
`TIME_MONTHS_PER_YEAR`. These are all given in seconds and whereas
they are called "week", "month" etc these names could represent
whatever fits your game. You can also set `TIME_UNITS` to a dict
mapping the name of a unit to its length in seconds (like `{"min":
60, ...}. If not given, sane defaults will be used.
customized by adding the `TIME_UNITS` dictionary to your settings
file. This maps unit names to their length, expressed in the smallest
unit. Here's the default as an example:
TIME_UNITS = {
"sec": 1,
"min": 60,
"hr": 60 * 60,
"hour": 60 * 60,
"day": 60 * 60 * 24,
"week": 60 * 60 * 24 * 7,
"month": 60 * 60 * 24 * 7 * 4,
"yr": 60 * 60 * 24 * 7 * 4 * 12,
"year": 60 * 60 * 24 * 7 * 4 * 12, }
When using a custom calendar, these time unit names are used as kwargs to
the converter functions in this module.
"""
@ -28,33 +37,23 @@ mapping the name of a unit to its length in seconds (like `{"min":
from django.conf import settings
from evennia import DefaultScript
from evennia.utils.create import create_script
from evennia.utils.gametime import gametime
from evennia.utils import gametime
# The game time speedup / slowdown relative real time
TIMEFACTOR = settings.TIME_FACTOR
# Game-time units, in game time seconds. These are supplied as a
# convenient measure for determining the current in-game time, e.g.
# when defining in-game events. The words month, week and year can be
# used to mean whatever units of time are used in your game.
SEC = 1
MIN = getattr(settings, "TIME_SECS_PER_MIN", 60)
HOUR = getattr(settings, "TIME_MINS_PER_HOUR", 60) * MIN
DAY = getattr(settings, "TIME_HOURS_PER_DAY", 24) * HOUR
WEEK = getattr(settings, "TIME_DAYS_PER_WEEK", 7) * DAY
MONTH = getattr(settings, "TIME_WEEKS_PER_MONTH", 4) * WEEK
YEAR = getattr(settings, "TIME_MONTHS_PER_YEAR", 12) * MONTH
# these are the unit names understood by the scheduler.
# These are the unit names understood by the scheduler.
# Each unit must be consistent and expressed in seconds.
UNITS = getattr(settings, "TIME_UNITS", {
"sec": SEC,
"min": MIN,
"hr": HOUR,
"hour": HOUR,
"day": DAY,
"week": WEEK,
"month": MONTH,
"year": YEAR,
"yr": YEAR,
})
# default custom calendar
"sec": 1,
"min": 60,
"hr": 60 * 60,
"hour": 60 * 60,
"day": 60 * 60 * 24,
"week": 60 * 60 * 24 * 7,
"month": 60 * 60 * 24 * 7 * 4,
"yr": 60 * 60 * 24 * 7 * 4 * 12,
"year": 60 * 60 * 24 * 7 * 4 * 12, })
def time_to_tuple(seconds, *divisors):
@ -92,7 +91,8 @@ def gametime_to_realtime(format=False, **kwargs):
Kwargs:
format (bool): Formatting the output.
times (int): The various components of the time (must match UNITS).
days, month etc (int): These are the names of time units that must
match the `settings.TIME_UNITS` dict keys.
Returns:
time (float or tuple): The realtime difference or the same
@ -163,7 +163,7 @@ def custom_gametime(absolute=False):
week, day, hour, minute, second).
"""
current = gametime(absolute=absolute)
current = gametime.gametime(absolute=absolute)
units = sorted(set(UNITS.values()), reverse=True)
del units[-1]
return time_to_tuple(current, *units)
@ -186,7 +186,7 @@ def real_seconds_until(**kwargs):
The number of real seconds before the given game time is up.
"""
current = gametime(absolute=True)
current = gametime.gametime(absolute=True)
units = sorted(set(UNITS.values()), reverse=True)
# Remove seconds from the tuple
del units[-1]
@ -232,25 +232,26 @@ def schedule(callback, repeat=False, **kwargs):
"""
Call the callback when the game time is up.
This function will setup a script that will be called when the
time corresponds to the game time. If the game is stopped for
more than a few seconds, the callback may be called with a slight
delay. If `repeat` is set to True, the callback will be called
again next time the game time matches the given time. The time
is given in units as keyword arguments. For instance:
>>> schedule(func, min=5, sec=0) # Will call next hour at :05.
>>> schedule(func, hour=2, min=30, sec=0) # Will call the next day at 02:30.
Args:
callback (function): the callback function that will be called [1].
repeat (bool, optional): should the callback be called regularly?
times (str: int): the time to call the callback.
[1] The callback must be a top-level function, since the script will
be persistent.
callback (function): The callback function that will be called. This
must be a top-level function since the script will be persistent.
repeat (bool, optional): Should the callback be called regularly?
day, month, etc (str: int): The time units to call the callback; should
match the keys of TIME_UNITS.
Returns:
The created script (Script).
script (Script): The created script.
Examples:
schedule(func, min=5, sec=0) # Will call next hour at :05.
schedule(func, hour=2, min=30, sec=0) # Will call the next day at 02:30.
Notes:
This function will setup a script that will be called when the
time corresponds to the game time. If the game is stopped for
more than a few seconds, the callback may be called with a
slight delay. If `repeat` is set to True, the callback will be
called again next time the game time matches the given time.
The time is given in units as keyword arguments.
"""
seconds = real_seconds_until(**kwargs)

View file

@ -68,6 +68,7 @@ Installation/testing:
"""
from __future__ import division
import datetime
import re
from django.conf import settings
from evennia import DefaultRoom
@ -129,12 +130,12 @@ class ExtendedRoom(DefaultRoom):
"""
Calculate the current time and season ids.
"""
# get the current time as parts of year and parts of day
# returns a tuple (years,months,weeks,days,hours,minutes,sec)
time = gametime.gametime(format=True)
month, hour = time[1], time[4]
season = float(month) / MONTHS_PER_YEAR
timeslot = float(hour) / HOURS_PER_DAY
# get the current time as parts of year and parts of day.
# we assume a standard calendar here and use 24h format.
timestamp = gametime.gametime(absolute=True)
datestamp = datetime.datetime.fromtimestamp(timestamp)
season = float(datestamp.month) / MONTHS_PER_YEAR
timeslot = float(datestamp.hour) / HOURS_PER_DAY
# figure out which slots these represent
if SEASONAL_BOUNDARIES[0] <= season < SEASONAL_BOUNDARIES[1]:

View file

@ -3,7 +3,6 @@ Testing suite for contrib folder
"""
from django.conf import settings
from evennia.commands.default.tests import CommandTest
from evennia.utils.test_resources import EvenniaTest
from mock import Mock
@ -172,40 +171,36 @@ from evennia.contrib import extended_room
from evennia import gametime
from evennia.objects.objects import DefaultRoom
# mock gametime to return 7th month, 10 in morning
gametime.gametime = Mock(return_value=(None, 7, None, None, 10))
# mock settings so we're not affected by a given server's hours of day/months in year
settings.TIME_MONTH_PER_YEAR = 12
settings.TIME_HOUR_PER_DAY = 24
class TestExtendedRoom(CommandTest):
room_typeclass = extended_room.ExtendedRoom
DETAIL_DESC = "A test detail."
SUMMER_DESC = "A summer description."
SPRING_DESC = "A spring description."
OLD_DESC = "Old description."
def setUp(self):
super(TestExtendedRoom, self).setUp()
self.room1.ndb.last_timeslot = "night"
self.room1.ndb.last_timeslot = "afternoon"
self.room1.ndb.last_season = "winter"
self.room1.db.details = {'testdetail': self.DETAIL_DESC}
self.room1.db.summer_desc = self.SUMMER_DESC
self.room1.db.spring_desc = self.SPRING_DESC
self.room1.db.desc = self.OLD_DESC
# mock gametime to return 7th month, 10 in morning
gametime.gametime = Mock(return_value=2975000766) # spring evening
def test_return_appearance(self):
# get the appearance of a non-extended room for contrast purposes
old_desc = DefaultRoom.return_appearance(self.room1, self.char1)
# the new appearance should be the old one, but with the desc switched
self.assertEqual(old_desc.replace(self.OLD_DESC, self.SUMMER_DESC), self.room1.return_appearance(self.char1))
self.assertEqual("summer", self.room1.ndb.last_season)
self.assertEqual("morning", self.room1.ndb.last_timeslot)
self.assertEqual(old_desc.replace(self.OLD_DESC, self.SPRING_DESC),
self.room1.return_appearance(self.char1))
self.assertEqual("spring", self.room1.ndb.last_season)
self.assertEqual("evening", self.room1.ndb.last_timeslot)
def test_return_detail(self):
self.assertEqual(self.DETAIL_DESC, self.room1.return_detail("testdetail"))
def test_cmdextendedlook(self):
self.call(extended_room.CmdExtendedLook(), "here", "Room(#1)\n%s" % self.SUMMER_DESC)
self.call(extended_room.CmdExtendedLook(), "here", "Room(#1)\n%s" % self.SPRING_DESC)
self.call(extended_room.CmdExtendedLook(), "testdetail", self.DETAIL_DESC)
self.call(extended_room.CmdExtendedLook(), "nonexistent", "Could not find 'nonexistent'.")
@ -220,15 +215,13 @@ class TestExtendedRoom(CommandTest):
self.call(extended_room.CmdExtendedDesc(), "", "Descriptions on Room:")
def test_cmdgametime(self):
self.call(extended_room.CmdGameTime(), "", "It's a summer day, in the morning.")
self.call(extended_room.CmdGameTime(), "", "It's a spring day, in the evening.")
# Test the contrib barter system
from evennia import create_object
from evennia.contrib import barter
class TestBarter(CommandTest):
def setUp(self):
@ -309,11 +302,11 @@ class TestBarter(CommandTest):
self.call(barter.CmdTradeHelp(), "", "Trading commands\n", caller=self.char1)
self.call(barter.CmdFinish(), ": Ending.", "You say, \"Ending.\"\n [You aborted trade. No deal was made.]")
# Test wilderness
from evennia.contrib import wilderness
from evennia import DefaultCharacter
class TestWilderness(EvenniaTest):
def setUp(self):
@ -429,3 +422,56 @@ class TestWilderness(EvenniaTest):
for direction, correct_loc in directions.iteritems(): # Not compatible with Python 3
new_loc = wilderness.get_new_coordinates(loc, direction)
self.assertEquals(new_loc, correct_loc, direction)
# Testing chargen contrib
from evennia.contrib import chargen
class TestChargen(CommandTest):
def test_ooclook(self):
self.call(chargen.CmdOOCLook(), "foo", "You have no characters to look at", caller=self.player)
self.call(chargen.CmdOOCLook(), "", "You, TestPlayer, are an OOC ghost without form.", caller=self.player)
def test_charcreate(self):
self.call(chargen.CmdOOCCharacterCreate(), "testchar", "The character testchar was successfully created!", caller=self.player)
self.call(chargen.CmdOOCCharacterCreate(), "testchar", "Character testchar already exists.", caller=self.player)
self.assertTrue(self.player.db._character_dbrefs)
self.call(chargen.CmdOOCLook(), "", "You, TestPlayer, are an OOC ghost without form.",caller=self.player)
self.call(chargen.CmdOOCLook(), "testchar", "testchar(", caller=self.player)
# Testing custom_gametime
from evennia.contrib import custom_gametime
def _testcallback():
pass
class TestCustomGameTime(EvenniaTest):
def setUp(self):
super(TestCustomGameTime, self).setUp()
gametime.gametime = Mock(return_value=2975000898.46) # does not seem to work
def tearDown(self):
if hasattr(self, "timescript"):
self.timescript.stop()
def test_time_to_tuple(self):
self.assertEqual(custom_gametime.time_to_tuple(10000, 34,2,4,6,1), (294, 2, 0, 0, 0, 0))
self.assertEqual(custom_gametime.time_to_tuple(10000, 3,3,4), (3333, 0, 0, 1))
self.assertEqual(custom_gametime.time_to_tuple(100000, 239,24,3), (418, 4, 0, 2))
def test_gametime_to_realtime(self):
self.assertEqual(custom_gametime.gametime_to_realtime(days=2, mins=4), 86520.0)
self.assertEqual(custom_gametime.gametime_to_realtime(format=True, days=2), (0,0,0,1,0,0,0))
def test_realtime_to_gametime(self):
self.assertEqual(custom_gametime.realtime_to_gametime(days=2, mins=34), 349680.0)
self.assertEqual(custom_gametime.realtime_to_gametime(days=2, mins=34, format=True), (0, 0, 0, 4, 1, 8, 0))
self.assertEqual(custom_gametime.realtime_to_gametime(format=True, days=2, mins=4), (0, 0, 0, 4, 0, 8, 0))
def test_custom_gametime(self):
self.assertEqual(custom_gametime.custom_gametime(), (102, 5, 2, 6, 21, 8, 18))
self.assertEqual(custom_gametime.custom_gametime(absolute=True), (102, 5, 2, 6, 21, 8, 18))
def test_real_seconds_until(self):
self.assertEqual(custom_gametime.real_seconds_until(year=2300, month=11, day=6), 31911667199.77)
def test_schedule(self):
self.timescript = custom_gametime.schedule(_testcallback, repeat=True, min=5, sec=0)
self.assertEqual(self.timescript.interval, 1700.7699999809265)