refactor PiLog to retain x,y values

This commit is contained in:
Brian S. Stephan 2020-10-24 11:47:36 -05:00
parent 10d73f570a
commit 4d94322c55
4 changed files with 78 additions and 38 deletions

View File

@ -1,21 +1,14 @@
# coding: utf-8 # coding: utf-8
"""Provide pi simulation results to IRC."""
import logging
from ircbot.lib import Plugin from ircbot.lib import Plugin
from pi.models import PiLog from pi.models import PiLog
log = logging.getLogger('pi.ircplugin')
class Pi(Plugin): class Pi(Plugin):
"""Use the Monte Carlo method to simulate pi.""" """Use the Monte Carlo method to simulate pi."""
def start(self): def start(self):
"""Set up the handlers.""" """Set up the handlers."""
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!pi$', self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!pi$',
self.handle_pi, -20) self.handle_pi, -20)
@ -23,17 +16,16 @@ class Pi(Plugin):
def stop(self): def stop(self):
"""Tear down handlers.""" """Tear down handlers."""
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_pi) self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_pi)
super(Pi, self).stop() super(Pi, self).stop()
def handle_pi(self, connection, event, match): def handle_pi(self, connection, event, match):
"""Handle the pi command by generating another value and presenting it.""" """Handle the pi command by generating another value and presenting it."""
newest, x, y = PiLog.objects.simulate()
newest, x, y, hit = PiLog.objects.simulate()
msg = ("({0:.10f}, {1:.10f}) is {2}within the unit circle. π is {5:.10f}. (i:{3:d} p:{4:d})" msg = ("({0:.10f}, {1:.10f}) is {2}within the unit circle. π is {5:.10f}. (i:{3:d} p:{4:d})"
"".format(x, y, "" if hit else "not ", newest.count_inside, newest.count_total, newest.value())) "".format(x, y, "" if newest.hit else "not ", newest.total_count_inside,
newest.total_count, newest.value))
return self.bot.reply(event, msg) return self.bot.reply(event, msg)

View File

@ -0,0 +1,23 @@
# Generated by Django 3.1.2 on 2020-10-24 16:27
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('pi', '0002_auto_20150521_2204'),
]
operations = [
migrations.RenameField(
model_name='pilog',
old_name='count_total',
new_name='total_count',
),
migrations.RenameField(
model_name='pilog',
old_name='count_inside',
new_name='total_count_inside',
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 3.1.2 on 2020-10-24 16:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pi', '0003_rename_count_fields'),
]
operations = [
migrations.AddField(
model_name='pilog',
name='simulation_x',
field=models.DecimalField(decimal_places=10, default=0.0, max_digits=11),
preserve_default=False,
),
migrations.AddField(
model_name='pilog',
name='simulation_y',
field=models.DecimalField(decimal_places=10, default=0.0, max_digits=11),
preserve_default=False,
),
]

View File

@ -1,67 +1,67 @@
"""Karma logging models.""" """Karma logging models."""
import logging
import math import math
import pytz
import random import random
import pytz
from django.conf import settings from django.conf import settings
from django.db import models from django.db import models
log = logging.getLogger('pi.models')
class PiLogManager(models.Manager): class PiLogManager(models.Manager):
"""Assemble some queries against PiLog.""" """Assemble some queries against PiLog."""
def simulate(self): def simulate(self):
"""Add one more entry to the log, and return it.""" """Add one more entry to the log, and return it."""
try: try:
latest = self.latest() latest = self.latest()
except PiLog.DoesNotExist: except PiLog.DoesNotExist:
latest = PiLog(count_inside=0, count_total=0) latest = PiLog.objects.create(simulation_x=0.0, simulation_y=0.0,
total_count_inside=0, total_count=0)
latest.save() latest.save()
inside = latest.count_inside inside = latest.total_count_inside
total = latest.count_total total = latest.total_count
x = random.random() x = random.random()
y = random.random() y = random.random()
hit = True if math.hypot(x,y) < 1 else False total += 1
if math.hypot(x, y) < 1:
inside += 1
if hit: newest = PiLog.objects.create(simulation_x=x, simulation_y=y,
newest = PiLog(count_inside=inside+1, count_total=total+1) total_count_inside=inside, total_count=total)
else:
newest = PiLog(count_inside=inside, count_total=total+1)
newest.save()
return newest, x, y, hit return newest, x, y
class PiLog(models.Model): class PiLog(models.Model):
"""Track pi as it is estimated over time.""" """Track pi as it is estimated over time."""
count_inside = models.PositiveIntegerField() simulation_x = models.DecimalField(max_digits=11, decimal_places=10)
count_total = models.PositiveIntegerField() simulation_y = models.DecimalField(max_digits=11, decimal_places=10)
total_count_inside = models.PositiveIntegerField()
total_count = models.PositiveIntegerField()
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
objects = PiLogManager() objects = PiLogManager()
class Meta: class Meta:
"""Options for the PiLog class."""
get_latest_by = 'created' get_latest_by = 'created'
def __str__(self): def __str__(self):
"""String representation.""" """Provide string representation."""
tz = pytz.timezone(settings.TIME_ZONE) tz = pytz.timezone(settings.TIME_ZONE)
return "({0:d}/{1:d}) @ {2:s}".format(self.count_inside, self.count_total, return "({0:d}/{1:d}) @ {2:s}".format(self.total_count_inside, self.total_count,
self.created.astimezone(tz).strftime('%Y-%m-%d %H:%M:%S %Z')) self.created.astimezone(tz).strftime('%Y-%m-%d %H:%M:%S %Z'))
@property
def value(self): def value(self):
"""Return this log entry's value of pi.""" """Return this log entry's estimated value of pi."""
return 4.0 * int(self.total_count_inside) / int(self.total_count)
return 4.0 * int(self.count_inside) / int(self.count_total) @property
def hit(self):
"""Return if this log entry is inside the unit circle."""
return math.hypot(self.simulation_x, self.simulation.y) < 1