Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
W
WTFd
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
FOSS-AG
WTFd
Commits
b166a642
Commit
b166a642
authored
Oct 11, 2019
by
Philipp Hochkamp
Browse files
Options
Downloads
Patches
Plain Diff
added autoreload of the leaderboard
closes
#30
parent
6f29769d
No related branches found
No related tags found
No related merge requests found
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
.gitignore
+1
-0
1 addition, 0 deletions
.gitignore
internal/orm.go
+48
-0
48 additions, 0 deletions
internal/orm.go
internal/server.go
+24
-331
24 additions, 331 deletions
internal/server.go
internal/structs.go
+227
-26
227 additions, 26 deletions
internal/structs.go
internal/util.go
+66
-0
66 additions, 0 deletions
internal/util.go
with
366 additions
and
357 deletions
.gitignore
+
1
−
0
View file @
b166a642
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
### Go ###
### Go ###
# Binaries for programs and plugins
# Binaries for programs and plugins
wtfd
*.exe
*.exe
*.exe~
*.exe~
*.dll
*.dll
...
...
This diff is collapsed.
Click to expand it.
internal/orm.go
+
48
−
0
View file @
b166a642
...
@@ -3,6 +3,7 @@ package wtfd
...
@@ -3,6 +3,7 @@ package wtfd
import
(
import
(
"errors"
"errors"
"fmt"
"fmt"
"golang.org/x/crypto/bcrypt"
"github.com/go-xorm/xorm"
"github.com/go-xorm/xorm"
_
"github.com/mattn/go-sqlite3"
// needed for xorm
_
"github.com/mattn/go-sqlite3"
// needed for xorm
"os"
"os"
...
@@ -48,6 +49,53 @@ func ormSync() {
...
@@ -48,6 +49,53 @@ func ormSync() {
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Login checks if password is right for username and returns the User object of it
func
Login
(
username
,
passwd
string
)
error
{
user
,
err
:=
Get
(
username
)
if
err
!=
nil
{
return
err
}
if
pwdRight
:=
user
.
ComparePassword
(
passwd
);
!
pwdRight
{
return
errWrongPassword
}
fmt
.
Printf
(
"User login: %s
\n
"
,
username
)
return
nil
}
// NewUser creates a new user object
func
NewUser
(
name
,
password
,
displayname
string
)
(
User
,
error
)
{
if
Contains
(
name
,
displayname
)
{
return
User
{},
errUserExisting
}
hash
,
err
:=
bcrypt
.
GenerateFromPassword
([]
byte
(
password
),
14
)
if
err
!=
nil
{
return
User
{},
err
}
fmt
.
Printf
(
"New User added: %s
\n
"
,
name
)
return
User
{
Name
:
name
,
Hash
:
hash
,
DisplayName
:
displayname
},
nil
}
// Contains looks if a username is in the datenbank
func
Contains
(
username
,
displayname
string
)
bool
{
count
,
_
:=
ormUserExists
(
User
{
Name
:
username
,
DisplayName
:
displayname
})
return
count
}
// Get gets username based on username
func
Get
(
username
string
)
(
User
,
error
)
{
user
,
err
:=
ormLoadUser
(
username
)
if
err
!=
nil
{
fmt
.
Printf
(
"Get Error: username: %v, user: %v, err: %v
\n
"
,
username
,
user
,
err
)
return
User
{},
err
}
return
user
,
err
}
func
ormStart
(
logFile
string
)
error
{
func
ormStart
(
logFile
string
)
error
{
var
err
error
var
err
error
engine
,
err
=
xorm
.
NewEngine
(
"sqlite3"
,
"./state.db"
)
engine
,
err
=
xorm
.
NewEngine
(
"sqlite3"
,
"./state.db"
)
...
...
This diff is collapsed.
Click to expand it.
internal/server.go
+
24
−
331
View file @
b166a642
...
@@ -10,16 +10,12 @@ import (
...
@@ -10,16 +10,12 @@ import (
"github.com/gorilla/mux"
"github.com/gorilla/mux"
"github.com/gorilla/securecookie"
"github.com/gorilla/securecookie"
"github.com/gorilla/sessions"
"github.com/gorilla/sessions"
"golang.org/x/crypto/bcrypt"
"html/template"
"html/template"
"io/ioutil"
"io/ioutil"
"log"
"log"
"math/rand"
"net/http"
"net/http"
"os"
"os"
"sort"
"strconv"
"strconv"
"strings"
)
)
const
(
const
(
...
@@ -76,281 +72,33 @@ var (
...
@@ -76,281 +72,33 @@ var (
maxrow
=
0
maxrow
=
0
)
)
// FillChallengeURI Fill host into each challenge's URI field and set HasURI
type
leaderboardPageData
struct
{
func
(
c
Challenges
)
FillChallengeURI
(
host
string
)
{
PageTitle
string
for
i
:=
range
c
{
User
*
User
if
c
[
i
]
.
URI
!=
""
{
IsUser
bool
c
[
i
]
.
HasURI
=
true
Points
int
c
[
i
]
.
URI
=
fmt
.
Sprintf
(
c
[
i
]
.
URI
,
host
)
Leaderboard
bool
}
else
{
AllUsers
[]
_ORMUser
c
[
i
]
.
HasURI
=
false
GeneratedName
string
}
Style
template
.
HTMLAttr
}
RowNums
[]
gridinfo
}
ColNums
[]
gridinfo
}
// Find finds a challenge from a string
type
mainPageData
struct
{
func
(
c
Challenges
)
Find
(
id
string
)
(
*
Challenge
,
error
)
{
PageTitle
string
for
_
,
v
:=
range
c
{
Challenges
[]
*
Challenge
if
v
.
Name
==
id
{
Leaderboard
bool
return
v
,
nil
SelectedChallengeID
string
}
HasSelectedChallengeID
bool
}
GeneratedName
string
return
&
Challenge
{},
fmt
.
Errorf
(
"no challenge with this id"
)
User
*
User
}
IsUser
bool
Points
int
// AllDepsCompleted checks if User u has completed all Dependent challenges of c
RowNums
[]
gridinfo
func
(
c
Challenge
)
AllDepsCompleted
(
u
User
)
bool
{
ColNums
[]
gridinfo
for
_
,
ch
:=
range
c
.
Deps
{
a
:=
false
for
_
,
uch
:=
range
u
.
Completed
{
if
uch
.
Name
==
ch
.
Name
{
a
=
true
}
}
if
a
==
false
{
return
false
}
}
return
true
}
// Contains looks if a username is in the datenbank
func
Contains
(
username
,
displayname
string
)
bool
{
count
,
_
:=
ormUserExists
(
User
{
Name
:
username
,
DisplayName
:
displayname
})
return
count
}
// HasSolvedChallenge returns true if u has solved chall
func
(
u
User
)
HasSolvedChallenge
(
chall
*
Challenge
)
bool
{
for
_
,
c
:=
range
u
.
Completed
{
if
c
.
Name
==
chall
.
Name
{
return
true
}
}
return
false
}
// CalculatePoints calculates Points and updates user.Points
func
(
u
*
User
)
CalculatePoints
()
{
points
:=
0
for
_
,
c
:=
range
u
.
Completed
{
points
+=
c
.
Points
}
u
.
Points
=
points
}
// Get gets username based on username
func
Get
(
username
string
)
(
User
,
error
)
{
user
,
err
:=
ormLoadUser
(
username
)
if
err
!=
nil
{
fmt
.
Printf
(
"Get Error: username: %v, user: %v, err: %v
\n
"
,
username
,
user
,
err
)
return
User
{},
err
}
return
user
,
err
}
func
resolveDeps
(
a
[]
string
)
[]
*
Challenge
{
var
toReturn
[]
*
Challenge
for
_
,
b
:=
range
a
{
for
_
,
c
:=
range
challs
{
if
c
.
Name
==
b
{
toReturn
=
append
(
toReturn
,
c
)
}
}
}
return
toReturn
}
func
countDeps
(
chall
*
Challenge
)
int
{
max
:=
1
if
len
(
chall
.
Deps
)
==
0
{
return
0
}
for
_
,
a
:=
range
chall
.
Deps
{
depcount
:=
countDeps
(
a
)
if
depcount
+
1
>
max
{
max
=
depcount
+
1
}
}
//return len(chall.DepIDs) + max
return
max
}
func
countAllDeps
()
{
for
i
:=
range
challs
{
challs
[
i
]
.
DepCount
=
countDeps
(
challs
[
i
])
}
}
func
reverseResolveAllDepIDs
()
{
for
i
:=
range
challs
{
for
j
:=
range
challs
{
if
i
!=
j
{
for
_
,
d
:=
range
challs
[
j
]
.
Deps
{
if
d
.
Name
==
challs
[
i
]
.
Name
{
// fmt.Printf("%s hat %s als revers dep\n", challs[i].Name, challs[j].Name)
challs
[
i
]
.
DepIDs
=
append
(
challs
[
i
]
.
DepIDs
,
challs
[
j
]
.
Name
)
break
}
}
}
}
}
}
func
calculateRowNums
()
{
cols
:=
make
(
map
[
int
][]
*
Challenge
)
for
_
,
chall
:=
range
challs
{
col
:=
chall
.
DepCount
cols
[
col
]
=
append
(
cols
[
col
],
chall
)
if
col
>
maxcol
{
maxcol
=
col
}
}
fmt
.
Println
(
"col
\t
[ <name>]
\t
min
\t
row"
)
for
i
:=
0
;
i
<=
maxcol
;
i
++
{
if
_
,
ok
:=
cols
[
i
];
!
ok
{
continue
}
//Skip empty columns
for
_
,
chall
:=
range
cols
[
i
]
{
chall
.
MinRow
=
0
for
_
,
dep
:=
range
chall
.
Deps
{
if
dep
.
Row
>
chall
.
MinRow
{
chall
.
MinRow
=
dep
.
Row
}
}
}
sort
.
Slice
(
cols
[
i
],
func
(
x
,
y
int
)
bool
{
if
cols
[
i
][
x
]
.
MinRow
==
cols
[
i
][
y
]
.
MinRow
{
if
len
(
cols
[
i
][
x
]
.
DepIDs
)
==
len
(
cols
[
i
][
y
]
.
DepIDs
)
{
return
stringCompareLess
(
cols
[
i
][
x
]
.
Name
,
cols
[
i
][
y
]
.
Name
)
}
else
{
// Sort as less (higher) if it has more dependecies
return
len
(
cols
[
i
][
x
]
.
DepIDs
)
>
len
(
cols
[
i
][
y
]
.
DepIDs
)
}
}
else
{
return
cols
[
i
][
x
]
.
MinRow
<
cols
[
i
][
y
]
.
MinRow
}
})
row
:=
0
for
j
:=
0
;
j
<
len
(
cols
[
i
]);
j
++
{
if
row
<
cols
[
i
][
j
]
.
MinRow
{
row
=
cols
[
i
][
j
]
.
MinRow
}
cols
[
i
][
j
]
.
Row
=
row
if
row
>
maxrow
{
maxrow
=
row
}
row
++
fmt
.
Printf
(
"%1d
\t
[%15s]
\t
%3d %3d
\n
"
,
i
,
cols
[
i
][
j
]
.
Name
,
cols
[
i
][
j
]
.
MinRow
,
cols
[
i
][
j
]
.
Row
)
}
}
}
// https://stackoverflow.com/a/35099450
func
stringCompareLess
(
si
,
sj
string
)
bool
{
var
siLower
=
strings
.
ToLower
(
si
)
var
sjLower
=
strings
.
ToLower
(
sj
)
if
siLower
==
sjLower
{
return
si
<
sj
}
return
siLower
<
sjLower
}
func
resolveChalls
(
jsons
[]
*
ChallengeJSON
)
{
i
:=
0
var
idsInChalls
[]
string
for
len
(
jsons
)
!=
0
{
// fmt.Printf("challs: %v, jsons: %v\n",challs,jsons)
this
:=
jsons
[
i
]
if
bContainsAllOfA
(
this
.
Deps
,
idsInChalls
)
{
idsInChalls
=
append
(
idsInChalls
,
this
.
Name
)
challs
=
append
(
challs
,
&
Challenge
{
Name
:
this
.
Name
,
Description
:
this
.
Description
,
Flag
:
this
.
Flag
,
URI
:
this
.
URI
,
Points
:
this
.
Points
,
Deps
:
resolveDeps
(
this
.
Deps
),
Solution
:
this
.
Solution
,
MinRow
:
-
1
,
Row
:
-
1
,
Author
:
this
.
Author
})
jsons
[
i
]
=
jsons
[
len
(
jsons
)
-
1
]
jsons
=
jsons
[
:
len
(
jsons
)
-
1
]
i
=
0
}
else
{
i
++
}
}
countAllDeps
()
reverseResolveAllDepIDs
()
calculateRowNums
()
}
// Login checks if password is right for username and returns the User object of it
func
Login
(
username
,
passwd
string
)
error
{
user
,
err
:=
Get
(
username
)
if
err
!=
nil
{
return
err
}
if
pwdRight
:=
user
.
ComparePassword
(
passwd
);
!
pwdRight
{
return
errWrongPassword
}
fmt
.
Printf
(
"User login: %s
\n
"
,
username
)
return
nil
}
// ComparePassword checks if the password is valid
func
(
u
*
User
)
ComparePassword
(
password
string
)
bool
{
return
bcrypt
.
CompareHashAndPassword
(
u
.
Hash
,
[]
byte
(
password
))
==
nil
}
// NewUser creates a new user object
func
NewUser
(
name
,
password
,
displayname
string
)
(
User
,
error
)
{
if
Contains
(
name
,
displayname
)
{
return
User
{},
errUserExisting
}
hash
,
err
:=
bcrypt
.
GenerateFromPassword
([]
byte
(
password
),
14
)
if
err
!=
nil
{
return
User
{},
err
}
fmt
.
Printf
(
"New User added: %s
\n
"
,
name
)
return
User
{
Name
:
name
,
Hash
:
hash
,
DisplayName
:
displayname
},
nil
}
func
generateUserName
()
(
string
,
error
)
{
var
name
string
for
_
,
s
:=
range
coolNames
{
if
exists
,
err
:=
ormDisplayNameExists
(
s
);
!
exists
{
if
err
!=
nil
{
return
""
,
err
}
name
=
s
break
}
}
}
for
name
==
""
{
name
=
strconv
.
FormatInt
(
rand
.
Int63
(),
10
)
if
exists
,
err
:=
ormDisplayNameExists
(
name
);
!
exists
{
if
err
!=
nil
{
return
""
,
err
}
name
=
""
}
}
return
name
,
nil
}
func
leaderboardpage
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
leaderboardpage
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
userobj
,
ok
:=
getUser
(
r
)
userobj
,
ok
:=
getUser
(
r
)
...
@@ -761,58 +509,3 @@ func Server() error {
...
@@ -761,58 +509,3 @@ func Server() error {
fmt
.
Printf
(
"WTFD Server Starting at port %d
\n
"
,
Port
)
fmt
.
Printf
(
"WTFD Server Starting at port %d
\n
"
,
Port
)
return
http
.
ListenAndServe
(
fmt
.
Sprintf
(
":%d"
,
Port
),
r
)
return
http
.
ListenAndServe
(
fmt
.
Sprintf
(
":%d"
,
Port
),
r
)
}
}
func
fixDeps
(
jsons
[]
*
ChallengeJSON
)
{
challsByName
:=
make
(
map
[
string
]
*
ChallengeJSON
)
for
_
,
chall
:=
range
jsons
{
challsByName
[
chall
.
Name
]
=
chall
}
for
_
,
chall
:=
range
jsons
{
keepDep
:=
make
(
map
[
string
]
bool
)
//Inititalize maps
for
_
,
dep
:=
range
chall
.
Deps
{
keepDep
[
dep
]
=
true
}
//Kick out redundant challenges
for
_
,
dep
:=
range
chall
.
Deps
{
for
_
,
depdep
:=
range
challsByName
[
dep
]
.
Deps
{
if
_
,
ok
:=
keepDep
[
depdep
];
ok
{
keepDep
[
depdep
]
=
false
}
}
}
//Rebould dependency array
var
newdeps
[]
string
for
name
,
keep
:=
range
keepDep
{
if
keep
{
newdeps
=
append
(
newdeps
,
name
)
}
}
//Write to struct
chall
.
Deps
=
newdeps
}
}
func
bContainsA
(
a
string
,
b
[]
string
)
bool
{
for
_
,
c
:=
range
b
{
if
a
==
c
{
return
true
}
}
return
false
}
func
bContainsAllOfA
(
a
,
b
[]
string
)
bool
{
for
_
,
c
:=
range
a
{
if
!
bContainsA
(
c
,
b
)
{
return
false
}
}
return
true
}
This diff is collapsed.
Click to expand it.
internal/structs.go
+
227
−
26
View file @
b166a642
package
wtfd
package
wtfd
import
(
import
(
"html/template"
"golang.org/x/crypto/bcrypt"
"fmt"
"sort"
)
)
// Challenges Array of challenges but in nice with funcitons
// Challenges Array of challenges but in nice with funcitons
...
@@ -54,33 +56,232 @@ type User struct {
...
@@ -54,33 +56,232 @@ type User struct {
Points
int
Points
int
}
}
type
leaderboardPageData
struct
{
PageTitle
string
User
*
User
IsUser
bool
Points
int
Leaderboard
bool
AllUsers
[]
_ORMUser
GeneratedName
string
Style
template
.
HTMLAttr
RowNums
[]
gridinfo
ColNums
[]
gridinfo
}
type
mainPageData
struct
{
PageTitle
string
Challenges
[]
*
Challenge
Leaderboard
bool
SelectedChallengeID
string
HasSelectedChallengeID
bool
GeneratedName
string
User
*
User
IsUser
bool
Points
int
RowNums
[]
gridinfo
ColNums
[]
gridinfo
}
type
gridinfo
struct
{
type
gridinfo
struct
{
Index
int
Index
int
Pos
int
Pos
int
}
}
// FillChallengeURI Fill host into each challenge's URI field and set HasURI
func
(
c
Challenges
)
FillChallengeURI
(
host
string
)
{
for
i
:=
range
c
{
if
c
[
i
]
.
URI
!=
""
{
c
[
i
]
.
HasURI
=
true
c
[
i
]
.
URI
=
fmt
.
Sprintf
(
c
[
i
]
.
URI
,
host
)
}
else
{
c
[
i
]
.
HasURI
=
false
}
}
}
// Find finds a challenge from a string
func
(
c
Challenges
)
Find
(
id
string
)
(
*
Challenge
,
error
)
{
for
_
,
v
:=
range
c
{
if
v
.
Name
==
id
{
return
v
,
nil
}
}
return
&
Challenge
{},
fmt
.
Errorf
(
"no challenge with this id"
)
}
// AllDepsCompleted checks if User u has completed all Dependent challenges of c
func
(
c
Challenge
)
AllDepsCompleted
(
u
User
)
bool
{
for
_
,
ch
:=
range
c
.
Deps
{
a
:=
false
for
_
,
uch
:=
range
u
.
Completed
{
if
uch
.
Name
==
ch
.
Name
{
a
=
true
}
}
if
a
==
false
{
return
false
}
}
return
true
}
// ComparePassword checks if the password is valid
func
(
u
*
User
)
ComparePassword
(
password
string
)
bool
{
return
bcrypt
.
CompareHashAndPassword
(
u
.
Hash
,
[]
byte
(
password
))
==
nil
}
func
resolveDeps
(
a
[]
string
)
[]
*
Challenge
{
var
toReturn
[]
*
Challenge
for
_
,
b
:=
range
a
{
for
_
,
c
:=
range
challs
{
if
c
.
Name
==
b
{
toReturn
=
append
(
toReturn
,
c
)
}
}
}
return
toReturn
}
func
countDeps
(
chall
*
Challenge
)
int
{
max
:=
1
if
len
(
chall
.
Deps
)
==
0
{
return
0
}
for
_
,
a
:=
range
chall
.
Deps
{
depcount
:=
countDeps
(
a
)
if
depcount
+
1
>
max
{
max
=
depcount
+
1
}
}
//return len(chall.DepIDs) + max
return
max
}
func
countAllDeps
()
{
for
i
:=
range
challs
{
challs
[
i
]
.
DepCount
=
countDeps
(
challs
[
i
])
}
}
func
reverseResolveAllDepIDs
()
{
for
i
:=
range
challs
{
for
j
:=
range
challs
{
if
i
!=
j
{
for
_
,
d
:=
range
challs
[
j
]
.
Deps
{
if
d
.
Name
==
challs
[
i
]
.
Name
{
// fmt.Printf("%s hat %s als revers dep\n", challs[i].Name, challs[j].Name)
challs
[
i
]
.
DepIDs
=
append
(
challs
[
i
]
.
DepIDs
,
challs
[
j
]
.
Name
)
break
}
}
}
}
}
}
func
calculateRowNums
()
{
cols
:=
make
(
map
[
int
][]
*
Challenge
)
for
_
,
chall
:=
range
challs
{
col
:=
chall
.
DepCount
cols
[
col
]
=
append
(
cols
[
col
],
chall
)
if
col
>
maxcol
{
maxcol
=
col
}
}
fmt
.
Println
(
"col
\t
[ <name>]
\t
min
\t
row"
)
for
i
:=
0
;
i
<=
maxcol
;
i
++
{
if
_
,
ok
:=
cols
[
i
];
!
ok
{
continue
}
//Skip empty columns
for
_
,
chall
:=
range
cols
[
i
]
{
chall
.
MinRow
=
0
for
_
,
dep
:=
range
chall
.
Deps
{
if
dep
.
Row
>
chall
.
MinRow
{
chall
.
MinRow
=
dep
.
Row
}
}
}
sort
.
Slice
(
cols
[
i
],
func
(
x
,
y
int
)
bool
{
if
cols
[
i
][
x
]
.
MinRow
==
cols
[
i
][
y
]
.
MinRow
{
if
len
(
cols
[
i
][
x
]
.
DepIDs
)
==
len
(
cols
[
i
][
y
]
.
DepIDs
)
{
return
stringCompareLess
(
cols
[
i
][
x
]
.
Name
,
cols
[
i
][
y
]
.
Name
)
}
else
{
// Sort as less (higher) if it has more dependecies
return
len
(
cols
[
i
][
x
]
.
DepIDs
)
>
len
(
cols
[
i
][
y
]
.
DepIDs
)
}
}
else
{
return
cols
[
i
][
x
]
.
MinRow
<
cols
[
i
][
y
]
.
MinRow
}
})
row
:=
0
for
j
:=
0
;
j
<
len
(
cols
[
i
]);
j
++
{
if
row
<
cols
[
i
][
j
]
.
MinRow
{
row
=
cols
[
i
][
j
]
.
MinRow
}
cols
[
i
][
j
]
.
Row
=
row
if
row
>
maxrow
{
maxrow
=
row
}
row
++
fmt
.
Printf
(
"%1d
\t
[%15s]
\t
%3d %3d
\n
"
,
i
,
cols
[
i
][
j
]
.
Name
,
cols
[
i
][
j
]
.
MinRow
,
cols
[
i
][
j
]
.
Row
)
}
}
}
func
resolveChalls
(
jsons
[]
*
ChallengeJSON
)
{
i
:=
0
var
idsInChalls
[]
string
for
len
(
jsons
)
!=
0
{
// fmt.Printf("challs: %v, jsons: %v\n",challs,jsons)
this
:=
jsons
[
i
]
if
bContainsAllOfA
(
this
.
Deps
,
idsInChalls
)
{
idsInChalls
=
append
(
idsInChalls
,
this
.
Name
)
challs
=
append
(
challs
,
&
Challenge
{
Name
:
this
.
Name
,
Description
:
this
.
Description
,
Flag
:
this
.
Flag
,
URI
:
this
.
URI
,
Points
:
this
.
Points
,
Deps
:
resolveDeps
(
this
.
Deps
),
Solution
:
this
.
Solution
,
MinRow
:
-
1
,
Row
:
-
1
,
Author
:
this
.
Author
})
jsons
[
i
]
=
jsons
[
len
(
jsons
)
-
1
]
jsons
=
jsons
[
:
len
(
jsons
)
-
1
]
i
=
0
}
else
{
i
++
}
}
countAllDeps
()
reverseResolveAllDepIDs
()
calculateRowNums
()
}
func
fixDeps
(
jsons
[]
*
ChallengeJSON
)
{
challsByName
:=
make
(
map
[
string
]
*
ChallengeJSON
)
for
_
,
chall
:=
range
jsons
{
challsByName
[
chall
.
Name
]
=
chall
}
for
_
,
chall
:=
range
jsons
{
keepDep
:=
make
(
map
[
string
]
bool
)
//Inititalize maps
for
_
,
dep
:=
range
chall
.
Deps
{
keepDep
[
dep
]
=
true
}
//Kick out redundant challenges
for
_
,
dep
:=
range
chall
.
Deps
{
for
_
,
depdep
:=
range
challsByName
[
dep
]
.
Deps
{
if
_
,
ok
:=
keepDep
[
depdep
];
ok
{
keepDep
[
depdep
]
=
false
}
}
}
//Rebould dependency array
var
newdeps
[]
string
for
name
,
keep
:=
range
keepDep
{
if
keep
{
newdeps
=
append
(
newdeps
,
name
)
}
}
//Write to struct
chall
.
Deps
=
newdeps
}
}
// HasSolvedChallenge returns true if u has solved chall
func
(
u
User
)
HasSolvedChallenge
(
chall
*
Challenge
)
bool
{
for
_
,
c
:=
range
u
.
Completed
{
if
c
.
Name
==
chall
.
Name
{
return
true
}
}
return
false
}
// CalculatePoints calculates Points and updates user.Points
func
(
u
*
User
)
CalculatePoints
()
{
points
:=
0
for
_
,
c
:=
range
u
.
Completed
{
points
+=
c
.
Points
}
u
.
Points
=
points
}
This diff is collapsed.
Click to expand it.
internal/util.go
0 → 100644
+
66
−
0
View file @
b166a642
package
wtfd
import
(
"strings"
"strconv"
"math/rand"
)
// https://stackoverflow.com/a/35099450
func
stringCompareLess
(
si
,
sj
string
)
bool
{
var
siLower
=
strings
.
ToLower
(
si
)
var
sjLower
=
strings
.
ToLower
(
sj
)
if
siLower
==
sjLower
{
return
si
<
sj
}
return
siLower
<
sjLower
}
func
generateUserName
()
(
string
,
error
)
{
var
name
string
for
_
,
s
:=
range
coolNames
{
if
exists
,
err
:=
ormDisplayNameExists
(
s
);
!
exists
{
if
err
!=
nil
{
return
""
,
err
}
name
=
s
break
}
}
for
name
==
""
{
name
=
strconv
.
FormatInt
(
rand
.
Int63
(),
10
)
if
exists
,
err
:=
ormDisplayNameExists
(
name
);
!
exists
{
if
err
!=
nil
{
return
""
,
err
}
name
=
""
}
}
return
name
,
nil
}
func
bContainsA
(
a
string
,
b
[]
string
)
bool
{
for
_
,
c
:=
range
b
{
if
a
==
c
{
return
true
}
}
return
false
}
func
bContainsAllOfA
(
a
,
b
[]
string
)
bool
{
for
_
,
c
:=
range
a
{
if
!
bContainsA
(
c
,
b
)
{
return
false
}
}
return
true
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment