Sign in to follow this  
Followers 0
big_daddy

How can I sort by, then by?

6 posts in this topic

I've made a working highscores list for my game. However I need it to sort two different ways, first by time, then by guesses.

Heres a script to work with.

#include <GUIConstants.au3>
#include <GuiListView.au3>

Global _
        $DeskHighCen = @DesktopHeight / 2, _
        $DeskWidCen = @DesktopWidth / 2
Dim $aNames[7] =["Bob", "Brian", "Paul", "Tom", "Karen", "Bill", "Kim"]
Dim $aWords[7] =["stops", "hooks", "light", "abbey", "about", "force", "macho"]

$Menu = GUICreate("", 200, 400, $DeskWidCen - 100, $DeskHighCen - 200)
$Button1 = GUICtrlCreateButton("Add Score", 5, 5, 70, 20)
$Button2 = GUICtrlCreateButton("Get Scores", 80, 5, 70, 20)
$ListView1 = GUICtrlCreateListView("#|Name|Word|Time|Guesses", 5, 30, 189, 370, _
        $LVS_REPORT, $LVS_EX_FULLROWSELECT)
GUISetState()

_GetHighScore()

While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then Exit
    If $msg = $Button1 Then _GetHighScore($aNames[Random(0, 6, 1)], _
            $aWords[Random(0, 6, 1)], Random(1, 10, 1), Random(1, 10, 1))
    If $msg = $Button2 Then _GetHighScore()
    Sleep(10)
WEnd

Func _GetHighScore($s_User = "", $s_Word = "", $i_Time = "", $i_Guesses = "")
    Dim $c[1][5]
    _GUICtrlListViewDeleteAllItems($ListView1)
    $a = IniReadSection(@ScriptDir & "\Scores.ini", "HighScores")
    If IsArray($a) Then
        If $s_User <> "" Then
            IniWrite(@ScriptDir & "\Scores.ini", "HighScores", $a[0][0] + 1, $s_User & "|" & $s_Word & "|" & $i_Time & "|" & $i_Guesses)
        EndIf
    Else
        If $s_User <> "" Then
            IniWrite(@ScriptDir & "\Scores.ini", "HighScores", 1, $s_User & "|" & $s_Word & "|" & $i_Time & "|" & $i_Guesses)
        EndIf
    EndIf
    $a = IniReadSection(@ScriptDir & "\Scores.ini", "HighScores")
    If IsArray($a) Then
        For $i = 1  To $a[0][0]
            ReDim $c[$i + 1][5]
            $b = StringSplit($a[$i][1], "|")
            For $y = 1 To $b[0]
                If $y = 3 Or $y = 4 Then
                    $c[$i][$y] = Number($b[$y])
                Else
                    $c[$i][$y] = $b[$y]
                EndIf
            Next
        Next
        _ArraySort($c, 0, 1, 0, 5, 3)
        ReDim $c[11][5]
        For $i = 1 To UBound($c) - 1
            _GUICtrlListViewInsertItem($ListView1, -1, $i & "|" & $c[$i][1] & _
                    "|" & $c[$i][2] & "|" & $c[$i][3] & "|" & $c[$i][4])
        Next
    EndIf
EndFunc   ;==>_GetHighScore

Share this post


Link to post
Share on other sites



might want to have a look at this

http://www.autoitscript.com/forum/index.ph...t.csv&st=0#

there are a few approaches

8)

Thanks for the link Valuater.

I don't want to use the Excel approach, but I just can't seem to grasp the concept of the others. Of course it has been one crazy monday, so that probably has something to do with it also.

Share this post


Link to post
Share on other sites

Thanks for the link Valuater.

I don't want to use the Excel approach, but I just can't seem to grasp the concept of the others. Of course it has been one crazy monday, so that probably has something to do with it also.

To do multi-field sort you need to create a calculated field and populate it with concatenation of fields you want to sort on in the same order as priority of sort.

For example, your record has 4 fields:

Field1 Field2 Field3 Field4

And you want to sort on Field3 and subsort on Field1

Create Field5 where data Field3 & Field1 - and now sort array on Field5

If you want to add subsort on Field2, then make Field5 = Field3 & Field1 & Field2

and sort on Field5.

The topic that Valuater refered to also describes a pitfall of having Fields containing non-text data.

In my case it was dates, or it could be time or just numbers. So preformat or convert data into text strings before populating Field5 in order to get true sorting.

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Hi,

cf the subsort Example in the zip file at "Array2D" link in my sig.

Allows formatting of cols as numbers too.

Best, Randall

MultiColumnSubSort2D.au3 2_16 ;randallc
;now needs index numbers ; negative for DESCENDING on that column, positive ascending ("0" ignored)
; any number?  columns as index here; if needed
#include "Array2D.au3"; for _ArrayFieldSort,_SubSort,_SubSortDo
;and ,_ArrayViewText_Array2DTo1String,_Array2DToArStrings,_ArrayReplace2DRow,_Array2DCreateFromArray,
Global $s_Row[8],$s_Row2[1] ; [OR; if entered as columns, you don't need the first transposition command]
local  $ar2_Array[1][1], $aRowArray[1]
$s_Row[0] = '5|1|4|4|7|4'
$s_Row[1] = '13|4|-7|7|.3|5'
$s_Row[2] = '11.7|0.4|-4|7|.2|5'
$s_Row[3] = '1|4|3|-7|.6|5'
$s_Row[4] = '24|0.4|8|-7|.9|4'
$s_Row[5] = '5|4|-2|-7|.0|7'
$s_Row[6] = '13|-4|4|7|1|4'
$s_Row[7] = '6|4|-7|7|.5|7'
;=======================================
$ar2_Array=_Array2DCreateFromArraySt($s_Row )
$i_Index="2|-4|3|6";,[numbered by base 1 (ie first col number is "1")] [Sorts on cols 2,4,3,6 {DESC on 4 as NEGATIVE}]
_Array2DFormatCols( $ar2_Array,$i_Index,"s")
_ArrayFieldSort($ar2_Array,$i_Index)
_ArrayViewText($ar2_Array, 'Asc/ Desc as STRINGS ['&$i_Index&'][rem index col is 1 less than named col numbers]"');#include"Array2Ds.au3" ; better 2D array viewer; try it!
_Array2DFormatCols( $ar2_Array,$i_Index)
_ArrayFieldSort($ar2_Array,$i_Index)
_ArrayViewText($ar2_Array, 'Asc/ Desc Array as NUMBERS ['&$i_Index&'][rem index col is 1 less than named col numbers]"');#include"Array2Ds.au3" ; better 2D array viewer; try it!
oÝ÷ Øô¶§+gyçlm«ÍêèØ6«­¬³
â¶×§jw[º2nëjºtߧ*ºv
ªëk&©¥æ«²Ú{VÚ±ç^Ø^­§cºËr¢êÚ®¶²¢ºÞ¸­zl]÷:»kÉ«­¢+Ø¥¹±ÕÅÕ½ÐíÉÉäɹÔÌÅÕ½Ðìì(ì¸(ì¸(ì¸($$ìôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôô(í}ÉÉåM½ÉÐ ÀÌØí°À°Ä°À°Ô°Ì¤($%}ÉÉå±ÑÉ ÀÌØí°À¤($$ÀÌØí¥}½ÉµÑ%¹àôÅÕ½ÐìÑðÔÅÕ½Ðìí½ÉµÐ½±ÌйÔ̹յÉ̽ÈͽÉÐ($%}ÉÉäɽɵÑ
½±Ì ÀÌØí°ÀÌØí¥}½ÉµÑ%¹à°ÅÕ½Ðí¸ÅÕ½Ðì¤($$ÀÌØí¥}MÕM½ÉÑ%¹àôÅÕ½ÐìÉðÑðÔÅÕ½ÐìíÝ¥±°Í½Éн¸½°È¥ÉÍС¹µÌ°±Ð½ÉµÐÌÑáФ°Ñ¡¸Ð°Ñ¡¸Ô¡½Ñ ̹յÉ̤($%}ÉÉ奱M½ÉÐ ÀÌØí°ÀÌØí¥}MÕM½ÉÑ%¹à¤($%}ÉÉå%¹ÍÉÐÉÍÐ ÀÌØí°ÅÕ½ÐìÅÕ½Ðì°À¤($$í}ÉÉåY¥ÝQáÐ ÀÌØí°ÌäíÐ¥¹ÍÉÐÌäì¤ì¥¹±ÕÅÕ½ÐíÉÉäÉ̹ÔÌÅÕ½ÐììÑÑÈÉÉÉäÙ¥ÝÈìÑÉä¥ÐÌÌì($$ìôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôô
This may still ahve bugs; I think , eg, if sorting a farther column before an earlier one; I will have to look into it; but I think it works for what you want here?

[PS I think the first new post of the UDF wiped out the 127 change; re-posted]

Edited by randallc

Share this post


Link to post
Share on other sites

Thank you for the suggestions. However this is what I came up with lastnight.

#include <GUIConstants.au3>
#include <GuiListView.au3>

Global _
        $DeskHighCen = @DesktopHeight / 2, _
        $DeskWidCen = @DesktopWidth / 2
$IniPath = @ScriptDir & "\Scores.ini"

Dim $aNames[7] =["Bob", "Brian", "Paul", "Tom", "Karen", "Bill", "Kim"]
Dim $aWords[7] =["stops", "hooks", "light", "abbey", "about", "force", "macho"]

$Menu = GUICreate("", 300, 400, $DeskWidCen - 100, $DeskHighCen - 200)
$Button1 = GUICtrlCreateButton("Add Score", 5, 5, 70, 20)
$Button2 = GUICtrlCreateButton("Get Scores", 80, 5, 70, 20)
$ListView1 = GUICtrlCreateListView("#|Name|Word|Time|Guesses", 5, 30, 289, 370, _
        $LVS_REPORT, $LVS_EX_FULLROWSELECT)
GUISetState()

_GetHighScore()

While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then Exit
    If $msg = $Button1 Then _WriteHighScore($aNames[Random(0, 6, 1)], _
            $aWords[Random(0, 6, 1)], Random(1, 10, 1), Random(1, 10, 1))
    If $msg = $Button2 Then _GetHighScore()
    Sleep(10)
WEnd

Func _GetHighScore()
    Dim $c[1][5]
    _GUICtrlListViewDeleteAllItems($ListView1)
    $aTimes = IniReadSection($IniPath, "HighScores")
    If IsArray($aTimes) Then
        For $i = 1  To $aTimes[0][0]
            ReDim $c[$i + 1][6]
            $b = StringSplit($aTimes[$i][1], "|")
            For $y = 1 To $b[0]
                If $y = 3 Or $y = 4 Then
                    $c[$i][$y] = Number($b[$y])
                Else
                    $c[$i][$y] = $b[$y]
                EndIf
            Next
        Next
        _ArraySort($c, 0, 1, 0, 5, 3)
        Do
            $Count = 0
            For $i = 1 To UBound($c) - 1
                If $c[$i][3] == $c[$i - 1][3]Then
                    If $c[$i][4] < $c[$i - 1][4]Then
                        $c[$i][5] = $i - 1
                        $Count += 1
                    Else
                        $c[$i][5] = $i
                    EndIf
                Else
                    $c[$i][5] = $i
                EndIf
            Next
            _ArraySort($c, 0, 1, 0, 6, 5)
        Until $Count = 0
        ReDim $c[21][5]
        For $i = 1 To UBound($c) - 1
            _GUICtrlListViewInsertItem($ListView1, -1, $i & "|" & $c[$i][1] & _
                    "|" & $c[$i][2] & "|" & $c[$i][3] & "|" & $c[$i][4])
        Next
    Else
        For $i = 1 To 20
            _GUICtrlListViewInsertItem($ListView1, -1, $i)
        Next
    EndIf
EndFunc   ;==>_GetHighScore

Func _WriteHighScore($s_User, $s_Word, $i_Time, $i_Guesses)
    $aTimes = IniReadSection($IniPath, "HighScores")
    If IsArray($aTimes) Then
        IniWrite($IniPath, "HighScores", $aTimes[0][0] + 1, $s_User & "|" & $s_Word & "|" & $i_Time & "|" & $i_Guesses)
    Else
        IniWrite($IniPath, "HighScores", 1, $s_User & "|" & $s_Word & "|" & $i_Time & "|" & $i_Guesses)
    EndIf
    _GetHighScore()
EndFunc   ;==>_WriteHighScore

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0