]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Use binary search to find first item for each category
authorSamual Lenks <samual@xonotic.org>
Fri, 11 Oct 2013 01:08:27 +0000 (21:08 -0400)
committerSamual Lenks <samual@xonotic.org>
Fri, 11 Oct 2013 01:08:27 +0000 (21:08 -0400)
qcsrc/menu/xonotic/serverlist.c

index 51e70f04556ea3b38ddd8f5c5a906dfdf8064339..f36a1229c1186a0d6d44b92fef2ea88b4126c2ce 100644 (file)
@@ -670,40 +670,77 @@ void XonoticServerList_draw(entity me)
                // ^ unfortunately no such optimization can be made-- we must process through the
                // entire list, otherwise there is no way to know which item is first in its category.
 
-               float cat, x;
-               for(i = 0; i < itemcount; ++i) // FIXME this loop is TOTALLY unacceptable (O(servers)). Make it O(categories * log(servers)). Yes, that is possible.
+               if(itemcount)
                {
-                       cat = gethostcachenumber(SLIST_FIELD_CATEGORY, i);
-                       if(cat)
+                       float cat = 0, x;
+                       float first, middle, last;
+                       float newfirst = 0;
+                       for(x = 1; x <= category_ent_count; ++x)
                        {
-                               if(category_draw_count == 0)
+                               first = newfirst;
+                               last = (itemcount - 1);
+                               middle = floor((first + last) / 2);
+
+                               while(first <= last)
                                {
-                                       category_name[category_draw_count] = cat;
-                                       category_item[category_draw_count] = i;
-                                       ++category_draw_count;
-                                       ++me.nItems;
+                                       cat = gethostcachenumber(SLIST_FIELD_CATEGORY, middle);
+                                       if(cat > x) { last = middle - 1; }
+                                       else if(cat == x)
+                                       {
+                                               if(middle == 0 || (gethostcachenumber(SLIST_FIELD_CATEGORY, middle - 1) != x)) // check if middle is the first of its category
+                                               {
+                                                       //print(sprintf("hit: x='%d', dc='%d', first='%d', middle='%d', last='%d', cat='%d'.\n", x, category_draw_count, first, middle, last, cat));
+                                                       category_name[category_draw_count] = cat;
+                                                       category_item[category_draw_count] = middle;
+                                                       ++category_draw_count;
+                                                       ++me.nItems;
+                                                       newfirst = middle + 1; // already scanned through these, skip 'em
+                                                       break;
+                                               }
+                                               else { last = middle - 1; } // nope, try again
+                                       }
+                                       else { first = middle + 1; }
+                                       middle = floor((first + last) / 2);
                                }
-                               else
+                       }
+               
+                       /*float cat = 0, i = 0, x = 0; 
+                       for(i = 0; i < itemcount; ++i) // FIXME this loop is TOTALLY unacceptable (O(servers)). Make it O(categories * log(servers)). Yes, that is possible.
+                       {
+                               cat = gethostcachenumber(SLIST_FIELD_CATEGORY, i);
+                               if(cat)
                                {
-                                       found = 0;
-                                       for(x = 0; x < category_draw_count; ++x) { if(cat == category_name[x]) { found = 1; } }
-                                       if not(found)
+                                       if(category_draw_count == 0)
                                        {
+                                               print(sprintf("hit: i='%d', dc='%d', cat='%d'.\n", i, category_draw_count, cat));
                                                category_name[category_draw_count] = cat;
                                                category_item[category_draw_count] = i;
                                                ++category_draw_count;
                                                ++me.nItems;
                                        }
+                                       else
+                                       {
+                                               found = 0;
+                                               for(x = 0; x < category_draw_count; ++x) { if(cat == category_name[x]) { found = 1; } }
+                                               if not(found)
+                                               {
+                                                       print(sprintf("hit: i='%d', dc='%d', cat='%d'.\n", i, category_draw_count, cat));
+                                                       category_name[category_draw_count] = cat;
+                                                       category_item[category_draw_count] = i;
+                                                       ++category_draw_count;
+                                                       ++me.nItems;
+                                               }
+                                       }
                                }
+                       }*/
+                       if(autocvar_menu_slist_categories_onlyifmultiple && (category_draw_count == 1))
+                       {
+                               category_name[0] = -1;
+                               category_item[0] = -1;
+                               category_draw_count = 0;
+                               me.nItems = itemcount;
                        }
                }
-               if(autocvar_menu_slist_categories_onlyifmultiple && (category_draw_count == 1))
-               {
-                       category_name[0] = -1;
-                       category_item[0] = -1;
-                       category_draw_count = 0;
-                       me.nItems = itemcount;
-               }
        }
        else { me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT); }