Sort and group items. Give each group a name.

This commit is contained in:
Empathic Qubit 2021-06-18 20:41:33 -04:00
parent e1dc5946ea
commit e161a2ae2a
4 changed files with 240 additions and 28 deletions

View file

@ -1,30 +1,67 @@
Scriptname _EQ_ItemRoulette_FormChunks extends Form
Activator Property FormChunks Auto
Form[] Property Children Auto
String Property ChunkName Auto
String Property StartName Auto
String Property EndName Auto
String[] ChildNames
Bool ChildNamesInitialized
String[] Function GetChildNames()
if !ChildNamesInitialized
String[] names = new String[127]
Int i = 0
ChildNamesInitialized = True
While(i < Children.Length)
Debug.Trace(i)
If Children[i] != None
names[i] = GetSortName(Children[i].GetName())
Debug.Trace(names[i])
Else
names[i] = ""
EndIf
i += 1
EndWhile
ChildNames = names
EndIf
return ChildNames
EndFunction
Bool Function StartsWith(String haystack, String needle)
return StringUtil.Find(haystack, needle, 0) == 0
EndFunction
String Function GetSortName(String name)
If StartsWith(name, "A ")
name = StringUtil.Substring(name, 2, StringUtil.GetLength(name) - 2)
ElseIf StartsWith(name, "The ")
name = StringUtil.Substring(name, 4, StringUtil.GetLength(name) - 4)
EndIf
return name
EndFunction
Function SortByName()
; based on "Optimized QuickSort - C Implementation" by darel rex finley (http://alienryderflex.com/quicksort/)
Int[] Beg = new Int[127]
Int[] End = new Int[127]
String[] Names = new String[127]
Int i = 0
Int i
Int L
Int R
Int swap
Form piv
String pivName
String[] Names = GetChildNames()
Beg[0] = 0
End[0] = Children.Length
While(i < Children.Length)
If Children[i] != None
Names[i] = Children[i].GetName()
Else
Names[i] = ""
EndIf
i += 1
EndWhile
i = 0
While (i >= 0)
@ -34,7 +71,7 @@ Function SortByName()
piv = Children[L]
pivName = Names[L]
While (L < R)
While ((Names[R] >= pivName) && (L < R))
While ((Names[R] == "" || Names[R] >= pivName) && (L < R))
R -= 1
EndWhile
If (L < R)
@ -42,7 +79,7 @@ Function SortByName()
Children[L] = Children[R]
L += 1
EndIf
While ((Names[L] <= pivName) && (L < R))
While ((pivName == "" || Names[L] <= pivName) && (L < R))
L += 1
EndWhile
If (L < R)
@ -69,13 +106,16 @@ Function SortByName()
i -= 1
EndIf
EndWhile
ChildNamesInitialized = False
EndFunction
Function SortByNameRecursive()
SortByName()
Int childIndex = 0
Form child
While childIndex < Children.Length
Form child = Children[childIndex]
child = Children[childIndex]
_EQ_ItemRoulette_FormChunks subChunk = (child as _EQ_ItemRoulette_FormChunks)
If(subChunk != None)
subChunk.SortByNameRecursive()
@ -90,11 +130,148 @@ Function PrintNamesRecursive()
Form child = Children[childIndex]
_EQ_ItemRoulette_FormChunks subChunk = (child as _EQ_ItemRoulette_FormChunks)
If(subChunk != None)
Debug.Trace("Chunk")
Debug.Trace("Chunk " + subChunk.ChunkName)
subChunk.PrintNamesRecursive()
ElseIf child != None
Debug.Trace(child.GetName())
EndIf
childIndex += 1
EndWhile
EndFunction
String Function Disambiguate(String source, String prev, String next)
Int i = 0
Int sourceLength = StringUtil.GetLength(source)
Int nextLength = StringUtil.GetLength(next)
Bool finished = False
String substr
if prev != ""
Int prevLength = StringUtil.GetLength(prev)
While !finished && i < sourceLength && i < prevLength
If StringUtil.GetNthChar(source, i) != StringUtil.GetNthChar(prev, i)
finished = True
Else
i += 1
EndIf
EndWhile
EndIf
While i < sourceLength && i < nextLength
If StringUtil.GetNthChar(source, i) != StringUtil.GetNthChar(next, i)
return StringUtil.Substring(source, 0, i + 1)
EndIf
i += 1
EndWhile
return StringUtil.Substring(source, 0, i)
EndFunction
Function FinishLastChunk(_EQ_ItemRoulette_FormChunks prevChunk, _EQ_ItemRoulette_FormChunks newChunk)
String prevChunkEndName = ""
if prevChunk != None
prevChunkEndName = prevChunk.EndName
EndIf
newChunk.ChunkName = Disambiguate(newChunk.StartName, prevChunkEndName, newChunk.EndName)
EndFunction
Int Function FindMinIndex(Int[] indices, String[] names)
Form currentItem
Int minIndex = -1
Int index
String min
String currentName
Int i = 0
_EQ_ItemRoulette_FormChunks oldChunk
While i < Children.Length
oldChunk = (Children[i] as _EQ_ItemRoulette_FormChunks)
If oldChunk != None
index = indices[i]
If index < oldChunk.Children.Length
currentItem = oldChunk.Children[index]
If currentItem != None
currentName = names[i]
If minIndex == -1 || currentName < min
min = currentName
minIndex = i
EndIf
EndIf
EndIf
EndIf
i += 1
EndWhile
return minIndex
EndFunction
_EQ_ItemRoulette_FormChunks Function GroupByName(ObjectReference placer)
_EQ_ItemRoulette_FormChunks groupChunks = ((placer.PlaceAtMe(FormChunks) as Form) as _EQ_ItemRoulette_FormChunks)
groupChunks.Children = new Form[127]
Int[] indices = new Int[127]
Int i = 0
While i < indices.Length
indices[i] = 0
i += 1
EndWhile
Form currentItem
_EQ_ItemRoulette_FormChunks oldChunk
String[] names = new String[127]
i = 0
While i < names.Length
oldChunk = (Children[i] as _EQ_ItemRoulette_FormChunks)
If oldChunk != None
names[i] = oldChunk.GetChildNames()[indices[i]]
EndIf
i += 1
EndWhile
Int chunkItemIndex = 5
Int chunkIndex = -1
Bool finishedScanningIndices = False
Int index
Int minIndex
_EQ_ItemRoulette_FormChunks newChunk
_EQ_ItemRoulette_FormChunks prevChunk
While !finishedScanningIndices
finishedScanningIndices = True
minIndex = FindMinIndex(indices, names)
If minIndex > -1
finishedScanningIndices = False
If chunkItemIndex >= 5
chunkItemIndex = 0
chunkIndex += 1
prevChunk = newChunk
newChunk = ((placer.PlaceAtMe(FormChunks) as Form) as _EQ_ItemRoulette_FormChunks)
newChunk.Children = new Form[5]
groupChunks.Children[chunkIndex] = newChunk
EndIf
index = indices[minIndex]
currentItem = (Children[minIndex] as _EQ_ItemRoulette_FormChunks).Children[index]
newChunk.Children[chunkItemIndex] = currentItem
if chunkItemIndex == 0
newChunk.StartName = names[minIndex]
if prevChunk != None
prevChunk.ChunkName += "-" + Disambiguate(prevChunk.EndName, prevChunk.StartName, newChunk.StartName)
EndIf
ElseIf chunkItemIndex == newChunk.Children.Length - 1
newChunk.EndName = names[minIndex]
FinishLastChunk(prevChunk, newChunk)
EndIf
indices[minIndex] = index + 1
names[minIndex] = ""
oldChunk = (Children[minIndex] as _EQ_ItemRoulette_FormChunks)
If oldChunk != None
If index + 1 < oldChunk.Children.Length
names[minIndex] = oldChunk.GetChildNames()[index + 1]
EndIf
EndIf
chunkItemIndex += 1
EndIf
EndWhile
FinishLastChunk(prevChunk, newChunk)
Return groupChunks
EndFunction

View file

@ -1,5 +1,13 @@
Scriptname _EQ_ItemRoulette_Main extends ReferenceAlias
Event OnItemAdded(Form baseItem, Int itemCount, ObjectReference itemRef, ObjectReference destContainer)
(GetOwningQuest() as _EQ_ItemRoulette_Quest).PlayerItemAdded(baseItem, itemCount, itemRef, destContainer)
EndEvent
Event OnItemRemoved(Form baseItem, Int itemCount, ObjectReference itemRef, ObjectReference destContainer)
(GetOwningQuest() as _EQ_ItemRoulette_Quest).PlayerItemRemoved(baseItem, itemCount, itemRef, destContainer)
EndEvent
Event OnPlayerLoadGame()
(GetOwningQuest() as _EQ_ItemRoulette_Quest).Main()
EndEvent

View file

@ -9,6 +9,7 @@ Form[] SpawnedForms
Form[] UnspawnedForms
ObjectReference Roulette
Bool ShouldSortInventoryItems
Int MAX_ITEMS
Float UI_TRANSLATE_SPEED
Float UI_DISTANCE
@ -50,9 +51,13 @@ Function Main()
index += 1
EndWhile
ShouldSortInventoryItems = True
Debug.Trace("Item Roulette loaded")
Roulette = PlayerRef.PlaceAtMe(_EQ_ItemRoulette_Roulette)
Roulette.SetMotionType(Roulette.Motion_Keyframed)
RegisterForModEvent("_EQ_ItemRoulette_Activate", "OnMyAction")
VRIK.VrikAddGestureAction("_EQ_ItemRoulette_Activate", "Activate Item Roulette")
RegisterForSingleUpdate(0.01)
@ -61,6 +66,11 @@ EndFunction
Event OnUpdate()
Float playerAngle = PlayerRef.GetAngleZ()
if ShouldSortInventoryItems
ShouldSortInventoryItems = False
SortInventoryItems()
EndIf
Int index = 0
While index < MAX_ITEMS
Form unspawnedForm = UnspawnedForms[index]
@ -104,22 +114,13 @@ Event OnUpdate()
RegisterForSingleUpdate(0.01)
EndEvent
Event OnMyAction(string eventName, string strArg, float numArg, Form sender)
Debug.Trace("VRIK activated me!")
;/
Get list of all inventory item names, sorted alphabetically
break into groups of five
find a common label for that group
group the groups in a similar manner until there are only five?
/;
Int numItems = PlayerRef.getNumItems()
Debug.Trace("Found " + numItems + " items")
Function SortInventoryItems()
_EQ_ItemRoulette_FormChunks sortChunks = ((Roulette.PlaceAtMe(FormChunks) as Form) as _EQ_ItemRoulette_FormChunks)
sortChunks.Children = new Form[127]
Int formIndex = 0
Int chunkIndex = -1
Int chunkItemIndex = 127
Int numItems = PlayerRef.getNumItems()
_EQ_ItemRoulette_FormChunks chunk
While formIndex < numItems
If chunkItemIndex >= 127
@ -134,13 +135,39 @@ Event OnMyAction(string eventName, string strArg, float numArg, Form sender)
chunkItemIndex += 1
EndWhile
Debug.StartStackProfiling()
Debug.Trace("Sorting")
sortChunks.SortByNameRecursive()
Debug.Trace("Printing")
sortChunks.PrintNamesRecursive()
Debug.Trace("Grouping")
_EQ_ItemRoulette_FormChunks groupChunks = sortChunks.GroupByName(Roulette)
Debug.Trace("Printing")
Debug.StopStackProfiling()
groupChunks.PrintNamesRecursive()
EndFunction
Function PlayerItemAdded(Form baseItem, Int itemCount, ObjectReference itemRef, ObjectReference destContainer)
ShouldSortInventoryItems = True
EndFunction
Function PlayerItemRemoved(Form baseItem, Int itemCount, ObjectReference itemRef, ObjectReference destContainer)
ShouldSortInventoryItems = True
EndFunction
Event OnMyAction(string eventName, string strArg, float numArg, Form sender)
Debug.Trace("VRIK activated me!")
;/
Get list of all inventory item names, sorted alphabetically
break into groups of five
find a common label for that group
group the groups in a similar manner until there are only five?
/;
Int numItems = PlayerRef.GetNumItems()
Debug.Trace("Found " + numItems + " items")
Int count = 0
formIndex = numItems
Int formIndex = numItems
While formIndex > 0 && formIndex > numItems - MAX_ITEMS
formIndex -= 1
count = numItems - formIndex

Binary file not shown.