Moved philo files into a philo subdirectory and added a setup.py file. Philo can...
[philo.git] / contrib / sobol / models.py
diff --git a/contrib/sobol/models.py b/contrib/sobol/models.py
deleted file mode 100644 (file)
index ee8187d..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-from django.conf.urls.defaults import patterns, url
-from django.contrib import messages
-from django.core.exceptions import ValidationError
-from django.db import models
-from django.http import HttpResponseRedirect, Http404, HttpResponse
-from django.utils import simplejson as json
-from django.utils.datastructures import SortedDict
-from philo.contrib.sobol import registry
-from philo.contrib.sobol.forms import SearchForm
-from philo.contrib.sobol.utils import HASH_REDIRECT_GET_KEY, URL_REDIRECT_GET_KEY, SEARCH_ARG_GET_KEY, check_redirect_hash
-from philo.exceptions import ViewCanNotProvideSubpath
-from philo.models import MultiView, Page
-from philo.models.fields import SlugMultipleChoiceField
-from philo.validators import RedirectValidator
-import datetime
-try:
-       import eventlet
-except:
-       eventlet = False
-
-
-class Search(models.Model):
-       string = models.TextField()
-       
-       def __unicode__(self):
-               return self.string
-       
-       def get_weighted_results(self, threshhold=None):
-               "Returns this search's results ordered by decreasing weight."
-               if not hasattr(self, '_weighted_results'):
-                       result_qs = self.result_urls.all()
-                       
-                       if threshhold is not None:
-                               result_qs = result_qs.filter(counts__datetime__gte=threshhold)
-                       
-                       results = [result for result in result_qs]
-                       
-                       results.sort(cmp=lambda x,y: cmp(y.weight, x.weight))
-                       
-                       self._weighted_results = results
-               
-               return self._weighted_results
-       
-       def get_favored_results(self, error=5, threshhold=None):
-               """
-               Calculate the set of most-favored results. A higher error
-               will cause this method to be more reticent about adding new
-               items.
-               
-               The thought is to see whether there are any results which
-               vastly outstrip the other options. As such, evenly-weighted
-               results should be grouped together and either added or
-               excluded as a group.
-               """
-               if not hasattr(self, '_favored_results'):
-                       results = self.get_weighted_results(threshhold)
-                       
-                       grouped_results = SortedDict()
-                       
-                       for result in results:
-                               grouped_results.setdefault(result.weight, []).append(result)
-                       
-                       self._favored_results = []
-                       
-                       for value, subresults in grouped_results.items():
-                               cost = error * sum([(value - result.weight)**2 for result in self._favored_results])
-                               if value > cost:
-                                       self._favored_results += subresults
-                               else:
-                                       break
-               return self._favored_results
-       
-       class Meta:
-               ordering = ['string']
-               verbose_name_plural = 'searches'
-
-
-class ResultURL(models.Model):
-       search = models.ForeignKey(Search, related_name='result_urls')
-       url = models.TextField(validators=[RedirectValidator()])
-       
-       def __unicode__(self):
-               return self.url
-       
-       def get_weight(self, threshhold=None):
-               if not hasattr(self, '_weight'):
-                       clicks = self.clicks.all()
-                       
-                       if threshhold is not None:
-                               clicks = clicks.filter(datetime__gte=threshhold)
-                       
-                       self._weight = sum([click.weight for click in clicks])
-               
-               return self._weight
-       weight = property(get_weight)
-       
-       class Meta:
-               ordering = ['url']
-
-
-class Click(models.Model):
-       result = models.ForeignKey(ResultURL, related_name='clicks')
-       datetime = models.DateTimeField()
-       
-       def __unicode__(self):
-               return self.datetime.strftime('%B %d, %Y %H:%M:%S')
-       
-       def get_weight(self, default=1, weighted=lambda value, days: value/days**2):
-               if not hasattr(self, '_weight'):
-                       days = (datetime.datetime.now() - self.datetime).days
-                       if days < 0:
-                               raise ValueError("Click dates must be in the past.")
-                       default = float(default)
-                       if days == 0:
-                               self._weight = float(default)
-                       else:
-                               self._weight = weighted(default, days)
-               return self._weight
-       weight = property(get_weight)
-       
-       def clean(self):
-               if self.datetime > datetime.datetime.now():
-                       raise ValidationError("Click dates must be in the past.")
-       
-       class Meta:
-               ordering = ['datetime']
-               get_latest_by = 'datetime'
-
-
-class SearchView(MultiView):
-       results_page = models.ForeignKey(Page, related_name='search_results_related')
-       searches = SlugMultipleChoiceField(choices=registry.iterchoices())
-       enable_ajax_api = models.BooleanField("Enable AJAX API", default=True, help_text="Search results will be available <i>only</i> by AJAX, not as template variables.")
-       placeholder_text = models.CharField(max_length=75, default="Search")
-       
-       search_form = SearchForm
-       
-       def __unicode__(self):
-               return u"%s (%s)" % (self.placeholder_text, u", ".join([display for slug, display in registry.iterchoices() if slug in self.searches]))
-       
-       def get_reverse_params(self, obj):
-               raise ViewCanNotProvideSubpath
-       
-       @property
-       def urlpatterns(self):
-               urlpatterns = patterns('',
-                       url(r'^$', self.results_view, name='results'),
-               )
-               if self.enable_ajax_api:
-                       urlpatterns += patterns('',
-                               url(r'^(?P<slug>[\w-]+)$', self.ajax_api_view, name='ajax_api_view')
-                       )
-               return urlpatterns
-       
-       def get_search_instance(self, slug, search_string):
-               return registry[slug](search_string.lower())
-       
-       def results_view(self, request, extra_context=None):
-               results = None
-               
-               context = self.get_context()
-               context.update(extra_context or {})
-               
-               if SEARCH_ARG_GET_KEY in request.GET:
-                       form = self.search_form(request.GET)
-                       
-                       if form.is_valid():
-                               search_string = request.GET[SEARCH_ARG_GET_KEY].lower()
-                               url = request.GET.get(URL_REDIRECT_GET_KEY)
-                               hash = request.GET.get(HASH_REDIRECT_GET_KEY)
-                               
-                               if url and hash:
-                                       if check_redirect_hash(hash, search_string, url):
-                                               # Create the necessary models
-                                               search = Search.objects.get_or_create(string=search_string)[0]
-                                               result_url = search.result_urls.get_or_create(url=url)[0]
-                                               result_url.clicks.create(datetime=datetime.datetime.now())
-                                               return HttpResponseRedirect(url)
-                                       else:
-                                               messages.add_message(request, messages.INFO, "The link you followed had been tampered with. Here are all the results for your search term instead!")
-                                               # TODO: Should search_string be escaped here?
-                                               return HttpResponseRedirect("%s?%s=%s" % (request.path, SEARCH_ARG_GET_KEY, search_string))
-                               if not self.enable_ajax_api:
-                                       search_instances = []
-                                       if eventlet:
-                                               pool = eventlet.GreenPool()
-                                       for slug in self.searches:
-                                               search_instance = self.get_search_instance(slug, search_string)
-                                               search_instances.append(search_instance)
-                                               if eventlet:
-                                                       pool.spawn_n(self.make_result_cache, search_instance)
-                                               else:
-                                                       self.make_result_cache(search_instance)
-                                       if eventlet:
-                                               pool.waitall()
-                                       context.update({
-                                               'searches': search_instances
-                                       })
-                               else:
-                                       context.update({
-                                               'searches': [{'verbose_name': verbose_name, 'slug': slug, 'url': self.reverse('ajax_api_view', kwargs={'slug': slug}, node=request.node), 'result_template': registry[slug].result_template} for slug, verbose_name in registry.iterchoices() if slug in self.searches]
-                                       })
-               else:
-                       form = SearchForm()
-               
-               context.update({
-                       'form': form
-               })
-               return self.results_page.render_to_response(request, extra_context=context)
-       
-       def make_result_cache(self, search_instance):
-               search_instance.results
-       
-       def ajax_api_view(self, request, slug, extra_context=None):
-               search_string = request.GET.get(SEARCH_ARG_GET_KEY)
-               
-               if not request.is_ajax() or not self.enable_ajax_api or slug not in self.searches or search_string is None:
-                       raise Http404
-               
-               search_instance = self.get_search_instance(slug, search_string)
-               response = HttpResponse(json.dumps({
-                       'results': [result.get_context() for result in search_instance.results],
-               }))
-               return response
\ No newline at end of file