From 1e6f8dc93a303d31747cd5d0d66bf4e90c17ff00 Mon Sep 17 00:00:00 2001
From: Robin Ward <robin.ward@gmail.com>
Date: Mon, 1 Apr 2013 13:49:35 -0400
Subject: [PATCH] Include uncategorized pinned topics on 'Hot'

---
 app/models/hot_topic.rb | 15 ++++++++++++++-
 lib/topic_query.rb      | 10 +++++++++-
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/app/models/hot_topic.rb b/app/models/hot_topic.rb
index d7ada5e7a..7ba79add9 100644
--- a/app/models/hot_topic.rb
+++ b/app/models/hot_topic.rb
@@ -3,7 +3,6 @@ class HotTopic < ActiveRecord::Base
   belongs_to :topic
   belongs_to :category
 
-
   # Here's the current idea behind the implementaiton of hot: random can produce good results!
   # Hot is currently made up of a random selection of high percentile topics. It includes mostly
   # new topics, but also some old ones for variety.
@@ -18,6 +17,16 @@ class HotTopic < ActiveRecord::Base
       new_days = 21               # how many days old we consider old
 
 
+      # Include all sticky uncategorized on Hot
+      exec_sql("INSERT INTO hot_topics (topic_id, score)
+                SELECT t.id, RANDOM()
+                FROM topics AS t
+                WHERE t.deleted_at IS NULL
+                  AND t.visible
+                  AND (NOT t.archived)
+                  AND t.pinned_at IS NOT NULL
+                  AND t.category_id IS NULL")
+
       # Include high percentile recent topics
       exec_sql("INSERT INTO hot_topics (topic_id, category_id, score)
                 SELECT t.id,
@@ -28,9 +37,11 @@ class HotTopic < ActiveRecord::Base
                   AND t.visible
                   AND (NOT t.closed)
                   AND (NOT t.archived)
+                  AND t.pinned_at IS NULL
                   AND t.archetype <> :private_message
                   AND created_at >= (CURRENT_TIMESTAMP - INTERVAL ':days_ago' DAY)
                   AND t.percent_rank < :hot_percentile
+                  AND NOT EXISTS(SELECT * FROM hot_topics AS ht2 WHERE ht2.topic_id = t.id)
                 LIMIT :limit",
                 hot_percentile: hot_percentile,
                 limit: ((1.0 - older_percentage) * max_hot_topics).round,
@@ -47,9 +58,11 @@ class HotTopic < ActiveRecord::Base
                   AND t.visible
                   AND (NOT t.closed)
                   AND (NOT t.archived)
+                  AND t.pinned_at IS NULL
                   AND t.archetype <> :private_message
                   AND created_at < (CURRENT_TIMESTAMP - INTERVAL ':days_ago' DAY)
                   AND t.percent_rank < :hot_percentile
+                  AND NOT EXISTS(SELECT * FROM hot_topics AS ht2 WHERE ht2.topic_id = t.id)
                 LIMIT :limit",
                 hot_percentile: hot_percentile,
                 limit: (older_percentage * max_hot_topics).round,
diff --git a/lib/topic_query.rb b/lib/topic_query.rb
index 6b9d6563f..ba7b062fb 100644
--- a/lib/topic_query.rb
+++ b/lib/topic_query.rb
@@ -27,6 +27,14 @@ class TopicQuery
        END DESC"
     end
 
+    def order_hotness
+      "CASE
+        WHEN (COALESCE(topics.pinned_at, '#{lowest_date}') > COALESCE(tu.cleared_pinned_at, '#{lowest_date}'))
+          THEN 100
+        ELSE hot_topics.score + (COALESCE(categories.hotness, 5.0) / 11.0)
+       END DESC"
+    end
+
     # If you've clearned the pin, use bumped_at, otherwise put it at the top
     def order_nocategory_with_pinned_sql
       "CASE
@@ -125,7 +133,7 @@ class TopicQuery
     return_list(unordered: true) do |list|
       # Find hot topics
       list = list.joins(:hot_topic)
-                 .order('hot_topics.score + (COALESCE(categories.hotness, 5.0) / 11.0) desc')
+                 .order(TopicQuery.order_hotness)
     end
   end