mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
Committing these because it seems to be the only way to get rid of them ever.
This commit is contained in:
@@ -1,54 +1,54 @@
|
||||
/*
|
||||
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
|
||||
(2012)
|
||||
*/
|
||||
|
||||
var/list/config_stream = list()
|
||||
var/list/servers = list()
|
||||
var/list/servernames = list()
|
||||
var/list/adminfiles = list()
|
||||
var/list/adminkeys = list()
|
||||
|
||||
proc/gen_configs()
|
||||
|
||||
|
||||
config_stream = dd_file2list("config.txt")
|
||||
|
||||
var/server_gen = 0 // if the stream is looking for servers
|
||||
var/admin_gen = 0 // if the stream is looking for admins
|
||||
for(var/line in config_stream)
|
||||
|
||||
if(line == "\[SERVERS\]")
|
||||
server_gen = 1
|
||||
if(admin_gen)
|
||||
admin_gen = 0
|
||||
|
||||
else if(line == "\[ADMINS\]")
|
||||
admin_gen = 1
|
||||
if(server_gen)
|
||||
server_gen = 0
|
||||
|
||||
else
|
||||
if(findtext(line, ".") && !findtext(line, "##"))
|
||||
if(server_gen)
|
||||
var/filterline = replacetext(line, " ", "")
|
||||
var/serverlink = copytext(filterline, findtext( filterline, ")") + 1)
|
||||
servers.Add(serverlink)
|
||||
servernames.Add( copytext(line, findtext(line, "("), findtext(line, ")") + 1))
|
||||
|
||||
else if(admin_gen)
|
||||
adminfiles.Add(line)
|
||||
/*
|
||||
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
|
||||
(2012)
|
||||
*/
|
||||
|
||||
var/list/config_stream = list()
|
||||
var/list/servers = list()
|
||||
var/list/servernames = list()
|
||||
var/list/adminfiles = list()
|
||||
var/list/adminkeys = list()
|
||||
|
||||
proc/gen_configs()
|
||||
|
||||
|
||||
config_stream = dd_file2list("config.txt")
|
||||
|
||||
var/server_gen = 0 // if the stream is looking for servers
|
||||
var/admin_gen = 0 // if the stream is looking for admins
|
||||
for(var/line in config_stream)
|
||||
|
||||
if(line == "\[SERVERS\]")
|
||||
server_gen = 1
|
||||
if(admin_gen)
|
||||
admin_gen = 0
|
||||
|
||||
else if(line == "\[ADMINS\]")
|
||||
admin_gen = 1
|
||||
if(server_gen)
|
||||
server_gen = 0
|
||||
|
||||
else
|
||||
if(findtext(line, ".") && !findtext(line, "##"))
|
||||
if(server_gen)
|
||||
var/filterline = replacetext(line, " ", "")
|
||||
var/serverlink = copytext(filterline, findtext( filterline, ")") + 1)
|
||||
servers.Add(serverlink)
|
||||
servernames.Add( copytext(line, findtext(line, "("), findtext(line, ")") + 1))
|
||||
|
||||
else if(admin_gen)
|
||||
adminfiles.Add(line)
|
||||
to_chat(world, line)
|
||||
|
||||
|
||||
// Generate the list of admins now
|
||||
|
||||
for(var/file in adminfiles)
|
||||
var/admin_config_stream = dd_file2list(file)
|
||||
|
||||
for(var/line in admin_config_stream)
|
||||
|
||||
var/akey = copytext(line, 1, findtext(line, " "))
|
||||
adminkeys.Add(akey)
|
||||
|
||||
|
||||
|
||||
|
||||
// Generate the list of admins now
|
||||
|
||||
for(var/file in adminfiles)
|
||||
var/admin_config_stream = dd_file2list(file)
|
||||
|
||||
for(var/line in admin_config_stream)
|
||||
|
||||
var/akey = copytext(line, 1, findtext(line, " "))
|
||||
adminkeys.Add(akey)
|
||||
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
// DM Environment file for Redirect_Tgstation.dme.
|
||||
// All manual changes should be made outside the BEGIN_ and END_ blocks.
|
||||
// New source code should be placed in .dm files: choose File/New --> Code File.
|
||||
|
||||
// BEGIN_INTERNALS
|
||||
// END_INTERNALS
|
||||
|
||||
// BEGIN_FILE_DIR
|
||||
#define FILE_DIR .
|
||||
// END_FILE_DIR
|
||||
|
||||
// BEGIN_PREFERENCES
|
||||
// END_PREFERENCES
|
||||
|
||||
// BEGIN_INCLUDE
|
||||
#include "Configurations.dm"
|
||||
#include "Redirector.dm"
|
||||
#include "textprocs.dm"
|
||||
#include "skin.dmf"
|
||||
// END_INCLUDE
|
||||
|
||||
// DM Environment file for Redirect_Tgstation.dme.
|
||||
// All manual changes should be made outside the BEGIN_ and END_ blocks.
|
||||
// New source code should be placed in .dm files: choose File/New --> Code File.
|
||||
|
||||
// BEGIN_INTERNALS
|
||||
// END_INTERNALS
|
||||
|
||||
// BEGIN_FILE_DIR
|
||||
#define FILE_DIR .
|
||||
// END_FILE_DIR
|
||||
|
||||
// BEGIN_PREFERENCES
|
||||
// END_PREFERENCES
|
||||
|
||||
// BEGIN_INCLUDE
|
||||
#include "Configurations.dm"
|
||||
#include "Redirector.dm"
|
||||
#include "textprocs.dm"
|
||||
#include "skin.dmf"
|
||||
// END_INCLUDE
|
||||
|
||||
|
||||
@@ -1,88 +1,88 @@
|
||||
/*
|
||||
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
|
||||
(2012)
|
||||
*/
|
||||
|
||||
/* TODO: work on server selection for detected admins */
|
||||
|
||||
|
||||
#define ADMINS 1
|
||||
#define PLAYERS 0
|
||||
|
||||
var/player_weight = 1 // players are more likely to join a server with less players
|
||||
var/admin_weight = 5 // admins are more likely to join a server with less admins
|
||||
|
||||
var/player_substr = "players=" // search for this substring to locate # of players
|
||||
var/admin_substr = "admins=" // search for this to locate # of admins
|
||||
|
||||
world
|
||||
name = "TGstation Redirector"
|
||||
|
||||
New()
|
||||
..()
|
||||
gen_configs()
|
||||
|
||||
/datum/server
|
||||
var/players = 0
|
||||
var/admins = 0
|
||||
var/weight = 0 // lower weight is good; highet weight is bad
|
||||
|
||||
var/link = ""
|
||||
|
||||
mob/Login()
|
||||
..()
|
||||
|
||||
var/list/weights = list()
|
||||
var/list/servers = list()
|
||||
for(var/x in global.servers)
|
||||
|
||||
/*
|
||||
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
|
||||
(2012)
|
||||
*/
|
||||
|
||||
/* TODO: work on server selection for detected admins */
|
||||
|
||||
|
||||
#define ADMINS 1
|
||||
#define PLAYERS 0
|
||||
|
||||
var/player_weight = 1 // players are more likely to join a server with less players
|
||||
var/admin_weight = 5 // admins are more likely to join a server with less admins
|
||||
|
||||
var/player_substr = "players=" // search for this substring to locate # of players
|
||||
var/admin_substr = "admins=" // search for this to locate # of admins
|
||||
|
||||
world
|
||||
name = "TGstation Redirector"
|
||||
|
||||
New()
|
||||
..()
|
||||
gen_configs()
|
||||
|
||||
/datum/server
|
||||
var/players = 0
|
||||
var/admins = 0
|
||||
var/weight = 0 // lower weight is good; highet weight is bad
|
||||
|
||||
var/link = ""
|
||||
|
||||
mob/Login()
|
||||
..()
|
||||
|
||||
var/list/weights = list()
|
||||
var/list/servers = list()
|
||||
for(var/x in global.servers)
|
||||
|
||||
to_chat(world, "[x] [servernames[ global.servers.Find(x) ]]")
|
||||
|
||||
var/info = world.Export("[x]?status")
|
||||
var/datum/server/S = new()
|
||||
S.players = extract(info, PLAYERS)
|
||||
S.admins = extract(info, ADMINS)
|
||||
|
||||
S.weight += player_weight * S.players
|
||||
S.link = x
|
||||
|
||||
|
||||
var/info = world.Export("[x]?status")
|
||||
var/datum/server/S = new()
|
||||
S.players = extract(info, PLAYERS)
|
||||
S.admins = extract(info, ADMINS)
|
||||
|
||||
S.weight += player_weight * S.players
|
||||
S.link = x
|
||||
|
||||
to_chat(world, S.players)
|
||||
to_chat(world, S.admins)
|
||||
|
||||
weights.Add(S.weight)
|
||||
servers.Add(S)
|
||||
|
||||
var/lowest = min(weights)
|
||||
var/serverlink
|
||||
for(var/datum/server/S in servers)
|
||||
if(S.weight == lowest)
|
||||
serverlink = S.link
|
||||
|
||||
|
||||
weights.Add(S.weight)
|
||||
servers.Add(S)
|
||||
|
||||
var/lowest = min(weights)
|
||||
var/serverlink
|
||||
for(var/datum/server/S in servers)
|
||||
if(S.weight == lowest)
|
||||
serverlink = S.link
|
||||
|
||||
to_chat(src, link(serverlink))
|
||||
|
||||
proc/extract(var/data, var/type = PLAYERS)
|
||||
|
||||
|
||||
var/nextpos = 0
|
||||
|
||||
if(type == PLAYERS)
|
||||
|
||||
nextpos = findtextEx(data, player_substr)
|
||||
nextpos += length(player_substr)
|
||||
|
||||
else
|
||||
|
||||
nextpos = findtextEx(data, admin_substr)
|
||||
nextpos += length(admin_substr)
|
||||
|
||||
var/returnval = ""
|
||||
|
||||
for(var/i = 1, i <= 10, i++)
|
||||
|
||||
var/interval = copytext(data, nextpos + (i-1), nextpos + i)
|
||||
if(interval == "&")
|
||||
break
|
||||
else
|
||||
returnval += interval
|
||||
|
||||
return returnval
|
||||
|
||||
proc/extract(var/data, var/type = PLAYERS)
|
||||
|
||||
|
||||
var/nextpos = 0
|
||||
|
||||
if(type == PLAYERS)
|
||||
|
||||
nextpos = findtextEx(data, player_substr)
|
||||
nextpos += length(player_substr)
|
||||
|
||||
else
|
||||
|
||||
nextpos = findtextEx(data, admin_substr)
|
||||
nextpos += length(admin_substr)
|
||||
|
||||
var/returnval = ""
|
||||
|
||||
for(var/i = 1, i <= 10, i++)
|
||||
|
||||
var/interval = copytext(data, nextpos + (i-1), nextpos + i)
|
||||
if(interval == "&")
|
||||
break
|
||||
else
|
||||
returnval += interval
|
||||
|
||||
return returnval
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
[SERVERS]
|
||||
## Simply enter a list of servers to poll. Be sure to specify a server name in parentheses.
|
||||
|
||||
(Sibyl #1) byond://game.nanotrasen.com:1337
|
||||
|
||||
(Sibyl #2) byond://game.nanotrasen.com:2337
|
||||
|
||||
|
||||
[ADMINS]
|
||||
## Specify some standard Windows filepaths (you may use relative paths) for admin txt lists to poll.
|
||||
|
||||
C:\SS13\config\admins.txt
|
||||
[SERVERS]
|
||||
## Simply enter a list of servers to poll. Be sure to specify a server name in parentheses.
|
||||
|
||||
(Sibyl #1) byond://game.nanotrasen.com:1337
|
||||
|
||||
(Sibyl #2) byond://game.nanotrasen.com:2337
|
||||
|
||||
|
||||
[ADMINS]
|
||||
## Specify some standard Windows filepaths (you may use relative paths) for admin txt lists to poll.
|
||||
|
||||
C:\SS13\config\admins.txt
|
||||
|
||||
@@ -1,149 +1,149 @@
|
||||
macro "macro"
|
||||
elem
|
||||
name = "North+REP"
|
||||
command = ".north"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "South+REP"
|
||||
command = ".south"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "East+REP"
|
||||
command = ".east"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "West+REP"
|
||||
command = ".west"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Northeast+REP"
|
||||
command = ".northeast"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Northwest+REP"
|
||||
command = ".northwest"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Southeast+REP"
|
||||
command = ".southeast"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Southwest+REP"
|
||||
command = ".southwest"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Center+REP"
|
||||
command = ".center"
|
||||
is-disabled = false
|
||||
|
||||
|
||||
menu "menu"
|
||||
elem
|
||||
name = "&Quit"
|
||||
command = ".quit"
|
||||
category = "&File"
|
||||
is-checked = false
|
||||
can-check = false
|
||||
group = ""
|
||||
is-disabled = false
|
||||
saved-params = "is-checked"
|
||||
|
||||
|
||||
window "window"
|
||||
elem "window"
|
||||
type = MAIN
|
||||
pos = 281,0
|
||||
size = 594x231
|
||||
anchor1 = none
|
||||
anchor2 = none
|
||||
font-family = ""
|
||||
font-size = 0
|
||||
font-style = ""
|
||||
text-color = #000000
|
||||
background-color = #000000
|
||||
is-visible = false
|
||||
is-disabled = false
|
||||
is-transparent = false
|
||||
is-default = true
|
||||
border = none
|
||||
drop-zone = false
|
||||
right-click = false
|
||||
saved-params = "pos;size;is-minimized;is-maximized"
|
||||
on-size = ""
|
||||
title = ""
|
||||
titlebar = true
|
||||
statusbar = false
|
||||
can-close = true
|
||||
can-minimize = true
|
||||
can-resize = true
|
||||
is-pane = false
|
||||
is-minimized = false
|
||||
is-maximized = false
|
||||
can-scroll = none
|
||||
icon = ""
|
||||
image = ""
|
||||
image-mode = stretch
|
||||
keep-aspect = false
|
||||
transparent-color = none
|
||||
alpha = 255
|
||||
macro = "macro"
|
||||
menu = ""
|
||||
on-close = ""
|
||||
elem "servers"
|
||||
type = GRID
|
||||
pos = 8,8
|
||||
size = 576x152
|
||||
anchor1 = none
|
||||
anchor2 = none
|
||||
font-family = ""
|
||||
font-size = 0
|
||||
font-style = ""
|
||||
text-color = #ffffff
|
||||
background-color = #000000
|
||||
is-visible = true
|
||||
is-disabled = false
|
||||
is-transparent = false
|
||||
is-default = false
|
||||
border = none
|
||||
drop-zone = true
|
||||
right-click = false
|
||||
saved-params = ""
|
||||
on-size = ""
|
||||
cells = 1x1
|
||||
current-cell = 1,1
|
||||
show-lines = none
|
||||
small-icons = true
|
||||
show-names = true
|
||||
enable-http-images = false
|
||||
link-color = #0000ff
|
||||
visited-color = #ff00ff
|
||||
line-color = #c0c0c0
|
||||
style = ""
|
||||
is-list = false
|
||||
elem "output1"
|
||||
type = OUTPUT
|
||||
pos = 8,168
|
||||
size = 576x56
|
||||
anchor1 = none
|
||||
anchor2 = none
|
||||
font-family = ""
|
||||
font-size = 0
|
||||
font-style = ""
|
||||
text-color = #ffffff
|
||||
background-color = #000000
|
||||
is-visible = true
|
||||
is-disabled = false
|
||||
is-transparent = false
|
||||
is-default = true
|
||||
border = none
|
||||
drop-zone = false
|
||||
right-click = false
|
||||
saved-params = "max-lines"
|
||||
on-size = ""
|
||||
link-color = #0000ff
|
||||
visited-color = #ff00ff
|
||||
style = ""
|
||||
enable-http-images = false
|
||||
max-lines = 1000
|
||||
image = ""
|
||||
|
||||
macro "macro"
|
||||
elem
|
||||
name = "North+REP"
|
||||
command = ".north"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "South+REP"
|
||||
command = ".south"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "East+REP"
|
||||
command = ".east"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "West+REP"
|
||||
command = ".west"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Northeast+REP"
|
||||
command = ".northeast"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Northwest+REP"
|
||||
command = ".northwest"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Southeast+REP"
|
||||
command = ".southeast"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Southwest+REP"
|
||||
command = ".southwest"
|
||||
is-disabled = false
|
||||
elem
|
||||
name = "Center+REP"
|
||||
command = ".center"
|
||||
is-disabled = false
|
||||
|
||||
|
||||
menu "menu"
|
||||
elem
|
||||
name = "&Quit"
|
||||
command = ".quit"
|
||||
category = "&File"
|
||||
is-checked = false
|
||||
can-check = false
|
||||
group = ""
|
||||
is-disabled = false
|
||||
saved-params = "is-checked"
|
||||
|
||||
|
||||
window "window"
|
||||
elem "window"
|
||||
type = MAIN
|
||||
pos = 281,0
|
||||
size = 594x231
|
||||
anchor1 = none
|
||||
anchor2 = none
|
||||
font-family = ""
|
||||
font-size = 0
|
||||
font-style = ""
|
||||
text-color = #000000
|
||||
background-color = #000000
|
||||
is-visible = false
|
||||
is-disabled = false
|
||||
is-transparent = false
|
||||
is-default = true
|
||||
border = none
|
||||
drop-zone = false
|
||||
right-click = false
|
||||
saved-params = "pos;size;is-minimized;is-maximized"
|
||||
on-size = ""
|
||||
title = ""
|
||||
titlebar = true
|
||||
statusbar = false
|
||||
can-close = true
|
||||
can-minimize = true
|
||||
can-resize = true
|
||||
is-pane = false
|
||||
is-minimized = false
|
||||
is-maximized = false
|
||||
can-scroll = none
|
||||
icon = ""
|
||||
image = ""
|
||||
image-mode = stretch
|
||||
keep-aspect = false
|
||||
transparent-color = none
|
||||
alpha = 255
|
||||
macro = "macro"
|
||||
menu = ""
|
||||
on-close = ""
|
||||
elem "servers"
|
||||
type = GRID
|
||||
pos = 8,8
|
||||
size = 576x152
|
||||
anchor1 = none
|
||||
anchor2 = none
|
||||
font-family = ""
|
||||
font-size = 0
|
||||
font-style = ""
|
||||
text-color = #ffffff
|
||||
background-color = #000000
|
||||
is-visible = true
|
||||
is-disabled = false
|
||||
is-transparent = false
|
||||
is-default = false
|
||||
border = none
|
||||
drop-zone = true
|
||||
right-click = false
|
||||
saved-params = ""
|
||||
on-size = ""
|
||||
cells = 1x1
|
||||
current-cell = 1,1
|
||||
show-lines = none
|
||||
small-icons = true
|
||||
show-names = true
|
||||
enable-http-images = false
|
||||
link-color = #0000ff
|
||||
visited-color = #ff00ff
|
||||
line-color = #c0c0c0
|
||||
style = ""
|
||||
is-list = false
|
||||
elem "output1"
|
||||
type = OUTPUT
|
||||
pos = 8,168
|
||||
size = 576x56
|
||||
anchor1 = none
|
||||
anchor2 = none
|
||||
font-family = ""
|
||||
font-size = 0
|
||||
font-style = ""
|
||||
text-color = #ffffff
|
||||
background-color = #000000
|
||||
is-visible = true
|
||||
is-disabled = false
|
||||
is-transparent = false
|
||||
is-default = true
|
||||
border = none
|
||||
drop-zone = false
|
||||
right-click = false
|
||||
saved-params = "max-lines"
|
||||
on-size = ""
|
||||
link-color = #0000ff
|
||||
visited-color = #ff00ff
|
||||
style = ""
|
||||
enable-http-images = false
|
||||
max-lines = 1000
|
||||
image = ""
|
||||
|
||||
|
||||
@@ -1,150 +1,150 @@
|
||||
/*
|
||||
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
|
||||
(2012)
|
||||
|
||||
NOTE: The below functions are part of BYOND user Deadron's "TextHandling" library.
|
||||
[ http://www.byond.com/developer/Deadron/TextHandling ]
|
||||
*/
|
||||
|
||||
|
||||
proc
|
||||
///////////////////
|
||||
// Reading files //
|
||||
///////////////////
|
||||
dd_file2list(file_path, separator = "\n")
|
||||
var/file
|
||||
if (isfile(file_path))
|
||||
file = file_path
|
||||
else
|
||||
file = file(file_path)
|
||||
return dd_text2list(file2text(file), separator)
|
||||
|
||||
|
||||
////////////////////
|
||||
// Replacing text //
|
||||
////////////////////
|
||||
dd_replacetext(text, search_string, replacement_string)
|
||||
// A nice way to do this is to split the text into an array based on the search_string,
|
||||
// then put it back together into text using replacement_string as the new separator.
|
||||
var/list/textList = dd_text2list(text, search_string)
|
||||
return dd_list2text(textList, replacement_string)
|
||||
|
||||
|
||||
dd_replaceText(text, search_string, replacement_string)
|
||||
var/list/textList = dd_text2List(text, search_string)
|
||||
return dd_list2text(textList, replacement_string)
|
||||
|
||||
|
||||
/////////////////////
|
||||
// Prefix checking //
|
||||
/////////////////////
|
||||
dd_hasprefix(text, prefix)
|
||||
var/start = 1
|
||||
var/end = lentext(prefix) + 1
|
||||
return findtext(text, prefix, start, end)
|
||||
|
||||
dd_hasPrefix(text, prefix)
|
||||
var/start = 1
|
||||
var/end = lentext(prefix) + 1
|
||||
return findtextEx(text, prefix, start, end)
|
||||
|
||||
|
||||
/////////////////////
|
||||
// Suffix checking //
|
||||
/////////////////////
|
||||
dd_hassuffix(text, suffix)
|
||||
var/start = length(text) - length(suffix)
|
||||
if (start) return findtext(text, suffix, start)
|
||||
|
||||
dd_hasSuffix(text, suffix)
|
||||
var/start = length(text) - length(suffix)
|
||||
if (start) return findtextEx(text, suffix, start)
|
||||
|
||||
/////////////////////////////
|
||||
// Turning text into lists //
|
||||
/////////////////////////////
|
||||
dd_text2list(text, separator)
|
||||
var/textlength = lentext(text)
|
||||
var/separatorlength = lentext(separator)
|
||||
var/list/textList = new /list()
|
||||
var/searchPosition = 1
|
||||
var/findPosition = 1
|
||||
var/buggyText
|
||||
while (1) // Loop forever.
|
||||
findPosition = findtext(text, separator, searchPosition, 0)
|
||||
buggyText = copytext(text, searchPosition, findPosition) // Everything from searchPosition to findPosition goes into a list element.
|
||||
textList += "[buggyText]" // Working around weird problem where "text" != "text" after this copytext().
|
||||
|
||||
searchPosition = findPosition + separatorlength // Skip over separator.
|
||||
if (findPosition == 0) // Didn't find anything at end of string so stop here.
|
||||
return textList
|
||||
else
|
||||
if (searchPosition > textlength) // Found separator at very end of string.
|
||||
textList += "" // So add empty element.
|
||||
return textList
|
||||
|
||||
dd_text2List(text, separator)
|
||||
var/textlength = lentext(text)
|
||||
var/separatorlength = lentext(separator)
|
||||
var/list/textList = new /list()
|
||||
var/searchPosition = 1
|
||||
var/findPosition = 1
|
||||
var/buggyText
|
||||
while (1) // Loop forever.
|
||||
findPosition = findtextEx(text, separator, searchPosition, 0)
|
||||
buggyText = copytext(text, searchPosition, findPosition) // Everything from searchPosition to findPosition goes into a list element.
|
||||
textList += "[buggyText]" // Working around weird problem where "text" != "text" after this copytext().
|
||||
|
||||
searchPosition = findPosition + separatorlength // Skip over separator.
|
||||
if (findPosition == 0) // Didn't find anything at end of string so stop here.
|
||||
return textList
|
||||
else
|
||||
if (searchPosition > textlength) // Found separator at very end of string.
|
||||
textList += "" // So add empty element.
|
||||
return textList
|
||||
|
||||
dd_list2text(list/the_list, separator)
|
||||
var/total = the_list.len
|
||||
if (total == 0) // Nothing to work with.
|
||||
return
|
||||
|
||||
var/newText = "[the_list[1]]" // Treats any object/number as text also.
|
||||
var/count
|
||||
for (count = 2, count <= total, count++)
|
||||
if (separator) newText += separator
|
||||
newText += "[the_list[count]]"
|
||||
return newText
|
||||
|
||||
dd_centertext(message, length)
|
||||
var/new_message = message
|
||||
var/size = length(message)
|
||||
if (size == length)
|
||||
return new_message
|
||||
if (size > length)
|
||||
return copytext(new_message, 1, length + 1)
|
||||
|
||||
// Need to pad text to center it.
|
||||
var/delta = length - size
|
||||
if (delta == 1)
|
||||
// Add one space after it.
|
||||
return new_message + " "
|
||||
|
||||
// Is this an odd number? If so, add extra space to front.
|
||||
if (delta % 2)
|
||||
new_message = " " + new_message
|
||||
delta--
|
||||
|
||||
// Divide delta in 2, add those spaces to both ends.
|
||||
delta = delta / 2
|
||||
var/spaces = ""
|
||||
for (var/count = 1, count <= delta, count++)
|
||||
spaces += " "
|
||||
return spaces + new_message + spaces
|
||||
|
||||
dd_limittext(message, length)
|
||||
// Truncates text to limit if necessary.
|
||||
var/size = length(message)
|
||||
if (size <= length)
|
||||
return message
|
||||
else
|
||||
/*
|
||||
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
|
||||
(2012)
|
||||
|
||||
NOTE: The below functions are part of BYOND user Deadron's "TextHandling" library.
|
||||
[ http://www.byond.com/developer/Deadron/TextHandling ]
|
||||
*/
|
||||
|
||||
|
||||
proc
|
||||
///////////////////
|
||||
// Reading files //
|
||||
///////////////////
|
||||
dd_file2list(file_path, separator = "\n")
|
||||
var/file
|
||||
if (isfile(file_path))
|
||||
file = file_path
|
||||
else
|
||||
file = file(file_path)
|
||||
return dd_text2list(file2text(file), separator)
|
||||
|
||||
|
||||
////////////////////
|
||||
// Replacing text //
|
||||
////////////////////
|
||||
dd_replacetext(text, search_string, replacement_string)
|
||||
// A nice way to do this is to split the text into an array based on the search_string,
|
||||
// then put it back together into text using replacement_string as the new separator.
|
||||
var/list/textList = dd_text2list(text, search_string)
|
||||
return dd_list2text(textList, replacement_string)
|
||||
|
||||
|
||||
dd_replaceText(text, search_string, replacement_string)
|
||||
var/list/textList = dd_text2List(text, search_string)
|
||||
return dd_list2text(textList, replacement_string)
|
||||
|
||||
|
||||
/////////////////////
|
||||
// Prefix checking //
|
||||
/////////////////////
|
||||
dd_hasprefix(text, prefix)
|
||||
var/start = 1
|
||||
var/end = lentext(prefix) + 1
|
||||
return findtext(text, prefix, start, end)
|
||||
|
||||
dd_hasPrefix(text, prefix)
|
||||
var/start = 1
|
||||
var/end = lentext(prefix) + 1
|
||||
return findtextEx(text, prefix, start, end)
|
||||
|
||||
|
||||
/////////////////////
|
||||
// Suffix checking //
|
||||
/////////////////////
|
||||
dd_hassuffix(text, suffix)
|
||||
var/start = length(text) - length(suffix)
|
||||
if (start) return findtext(text, suffix, start)
|
||||
|
||||
dd_hasSuffix(text, suffix)
|
||||
var/start = length(text) - length(suffix)
|
||||
if (start) return findtextEx(text, suffix, start)
|
||||
|
||||
/////////////////////////////
|
||||
// Turning text into lists //
|
||||
/////////////////////////////
|
||||
dd_text2list(text, separator)
|
||||
var/textlength = lentext(text)
|
||||
var/separatorlength = lentext(separator)
|
||||
var/list/textList = new /list()
|
||||
var/searchPosition = 1
|
||||
var/findPosition = 1
|
||||
var/buggyText
|
||||
while (1) // Loop forever.
|
||||
findPosition = findtext(text, separator, searchPosition, 0)
|
||||
buggyText = copytext(text, searchPosition, findPosition) // Everything from searchPosition to findPosition goes into a list element.
|
||||
textList += "[buggyText]" // Working around weird problem where "text" != "text" after this copytext().
|
||||
|
||||
searchPosition = findPosition + separatorlength // Skip over separator.
|
||||
if (findPosition == 0) // Didn't find anything at end of string so stop here.
|
||||
return textList
|
||||
else
|
||||
if (searchPosition > textlength) // Found separator at very end of string.
|
||||
textList += "" // So add empty element.
|
||||
return textList
|
||||
|
||||
dd_text2List(text, separator)
|
||||
var/textlength = lentext(text)
|
||||
var/separatorlength = lentext(separator)
|
||||
var/list/textList = new /list()
|
||||
var/searchPosition = 1
|
||||
var/findPosition = 1
|
||||
var/buggyText
|
||||
while (1) // Loop forever.
|
||||
findPosition = findtextEx(text, separator, searchPosition, 0)
|
||||
buggyText = copytext(text, searchPosition, findPosition) // Everything from searchPosition to findPosition goes into a list element.
|
||||
textList += "[buggyText]" // Working around weird problem where "text" != "text" after this copytext().
|
||||
|
||||
searchPosition = findPosition + separatorlength // Skip over separator.
|
||||
if (findPosition == 0) // Didn't find anything at end of string so stop here.
|
||||
return textList
|
||||
else
|
||||
if (searchPosition > textlength) // Found separator at very end of string.
|
||||
textList += "" // So add empty element.
|
||||
return textList
|
||||
|
||||
dd_list2text(list/the_list, separator)
|
||||
var/total = the_list.len
|
||||
if (total == 0) // Nothing to work with.
|
||||
return
|
||||
|
||||
var/newText = "[the_list[1]]" // Treats any object/number as text also.
|
||||
var/count
|
||||
for (count = 2, count <= total, count++)
|
||||
if (separator) newText += separator
|
||||
newText += "[the_list[count]]"
|
||||
return newText
|
||||
|
||||
dd_centertext(message, length)
|
||||
var/new_message = message
|
||||
var/size = length(message)
|
||||
if (size == length)
|
||||
return new_message
|
||||
if (size > length)
|
||||
return copytext(new_message, 1, length + 1)
|
||||
|
||||
// Need to pad text to center it.
|
||||
var/delta = length - size
|
||||
if (delta == 1)
|
||||
// Add one space after it.
|
||||
return new_message + " "
|
||||
|
||||
// Is this an odd number? If so, add extra space to front.
|
||||
if (delta % 2)
|
||||
new_message = " " + new_message
|
||||
delta--
|
||||
|
||||
// Divide delta in 2, add those spaces to both ends.
|
||||
delta = delta / 2
|
||||
var/spaces = ""
|
||||
for (var/count = 1, count <= delta, count++)
|
||||
spaces += " "
|
||||
return spaces + new_message + spaces
|
||||
|
||||
dd_limittext(message, length)
|
||||
// Truncates text to limit if necessary.
|
||||
var/size = length(message)
|
||||
if (size <= length)
|
||||
return message
|
||||
else
|
||||
return copytext(message, 1, length + 1)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,314 +1,314 @@
|
||||
/* Runtime Condenser by Nodrak
|
||||
* This will sum up identical runtimes into one, giving a total of how many times it occured. The first occurance
|
||||
* of the runtime will log the proc, source, usr and src, the rest will just add to the total. Infinite loops will
|
||||
* also be caught and displayed (if any) above the list of runtimes.
|
||||
*
|
||||
* How to use:
|
||||
* 1) Copy and paste your list of runtimes from Dream Daemon into input.exe
|
||||
* 2) Run RuntimeCondenser.exe
|
||||
* 3) Open output.txt for a condensed report of the runtimes
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
//Make all of these global. It's bad yes, but it's a small program so it really doesn't affect anything.
|
||||
//Because hardcoded numbers are bad :(
|
||||
const unsigned short maxStorage = 99; //100 - 1
|
||||
|
||||
//What we use to read input
|
||||
string currentLine = "Blank";
|
||||
string nextLine = "Blank";
|
||||
|
||||
//Stores lines we want to keep to print out
|
||||
string storedRuntime[maxStorage+1];
|
||||
string storedProc[maxStorage+1];
|
||||
string storedSource[maxStorage+1];
|
||||
string storedUsr[maxStorage+1];
|
||||
string storedSrc[maxStorage+1];
|
||||
|
||||
//Stat tracking stuff for output
|
||||
unsigned int totalRuntimes = 0;
|
||||
unsigned int totalUniqueRuntimes = 0;
|
||||
unsigned int totalInfiniteLoops = 0;
|
||||
unsigned int totalUniqueInfiniteLoops = 0;
|
||||
|
||||
//Misc
|
||||
unsigned int numRuntime[maxStorage+1]; //Number of times a specific runtime has occured
|
||||
bool checkNextLines = false; //Used in case byond has condensed a large number of similar runtimes
|
||||
int storedIterator = 0; //Used to remember where we stored the runtime
|
||||
|
||||
bool readFromFile()
|
||||
{
|
||||
//Open file to read
|
||||
ifstream inputFile("input.txt");
|
||||
|
||||
if(inputFile.is_open())
|
||||
{
|
||||
while(!inputFile.eof()) //Until end of file
|
||||
{
|
||||
//If we've run out of storage
|
||||
if(storedRuntime[maxStorage] != "Blank") break;
|
||||
|
||||
//Update our lines
|
||||
currentLine = nextLine;
|
||||
getline(inputFile, nextLine);
|
||||
|
||||
//After finding a new runtime, check to see if there are extra values to store
|
||||
if(checkNextLines)
|
||||
{
|
||||
//Skip ahead
|
||||
currentLine = nextLine;
|
||||
getline(inputFile, nextLine);
|
||||
|
||||
//If we find this, we have new stuff to store
|
||||
if(nextLine.find("usr:") != std::string::npos)
|
||||
{
|
||||
//Store more info
|
||||
storedSource[storedIterator] = currentLine;
|
||||
storedUsr[storedIterator] = nextLine;
|
||||
|
||||
//Skip ahead again
|
||||
currentLine = nextLine;
|
||||
getline(inputFile, nextLine);
|
||||
|
||||
//Store the last of the info
|
||||
storedSrc[storedIterator] = nextLine;
|
||||
}
|
||||
checkNextLines = false;
|
||||
}
|
||||
|
||||
//Found an infinite loop!
|
||||
if(currentLine.find("Infinite loop suspected") != std::string::npos || currentLine.find("Maximum recursion level reached") != std::string::npos)
|
||||
{
|
||||
totalInfiniteLoops++;
|
||||
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
//We've already encountered this
|
||||
if(currentLine == storedRuntime[i])
|
||||
{
|
||||
numRuntime[i]++;
|
||||
break;
|
||||
}
|
||||
|
||||
//We've never encoutnered this
|
||||
if(storedRuntime[i] == "Blank")
|
||||
{
|
||||
storedRuntime[i] = currentLine;
|
||||
currentLine = nextLine;
|
||||
getline(inputFile, nextLine); //Skip the "if this is not an infinite loop" line
|
||||
storedProc[i] = nextLine;
|
||||
numRuntime[i] = 1;
|
||||
checkNextLines = true;
|
||||
storedIterator = i;
|
||||
totalUniqueInfiniteLoops++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Found a runtime!
|
||||
else if(currentLine.find("runtime error:") != std::string::npos)
|
||||
{
|
||||
totalRuntimes++;
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
//We've already encountered this
|
||||
if(currentLine == storedRuntime[i])
|
||||
{
|
||||
numRuntime[i]++;
|
||||
break;
|
||||
}
|
||||
|
||||
//We've never encoutnered this
|
||||
if(storedRuntime[i] == "Blank")
|
||||
{
|
||||
storedRuntime[i] = currentLine;
|
||||
storedProc[i] = nextLine;
|
||||
numRuntime[i] = 1;
|
||||
checkNextLines = true;
|
||||
storedIterator = i;
|
||||
totalUniqueRuntimes++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeToFile()
|
||||
{
|
||||
//Open and clear the file
|
||||
ofstream outputFile("Output.txt", ios::trunc);
|
||||
|
||||
if(outputFile.is_open())
|
||||
{
|
||||
outputFile << "Note: The proc name, source file, src and usr are all from the FIRST of the identical runtimes. Everything else is cropped.\n\n";
|
||||
if(totalUniqueInfiniteLoops > 0)
|
||||
{
|
||||
outputFile << "Total unique infinite loops: " << totalUniqueInfiniteLoops << endl;
|
||||
}
|
||||
if(totalInfiniteLoops > 0)
|
||||
{
|
||||
outputFile << "Total infinite loops: " << totalInfiniteLoops << endl;
|
||||
}
|
||||
outputFile << "Total unique runtimes: " << totalUniqueRuntimes << endl;
|
||||
outputFile << "Total runtimes: " << totalRuntimes << endl << endl;
|
||||
|
||||
//Display a warning if we've hit the maximum space we've allocated for storage
|
||||
if(totalUniqueRuntimes + totalUniqueInfiniteLoops >= maxStorage)
|
||||
{
|
||||
outputFile << "Warning: The maximum number of unique runtimes has been hit. If there were more, they have been cropped out.\n\n";
|
||||
}
|
||||
|
||||
|
||||
//If we have infinite loops, display them first.
|
||||
if(totalInfiniteLoops > 0)
|
||||
{
|
||||
outputFile << "** Infinite loops **";
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
if(storedRuntime[i].find("Infinite loop suspected") != std::string::npos || storedRuntime[i].find("Maximum recursion level reached") != std::string::npos)
|
||||
{
|
||||
if(numRuntime[i] != 0) outputFile << endl << endl << "The following infinite loop has occured " << numRuntime[i] << " time(s).\n";
|
||||
if(storedRuntime[i] != "Blank") outputFile << storedRuntime[i] << endl;
|
||||
if(storedProc[i] != "Blank") outputFile << storedProc[i] << endl;
|
||||
if(storedSource[i] != "Blank") outputFile << storedSource[i] << endl;
|
||||
if(storedUsr[i] != "Blank") outputFile << storedUsr[i] << endl;
|
||||
if(storedSrc[i] != "Blank") outputFile << storedSrc[i] << endl;
|
||||
}
|
||||
}
|
||||
outputFile << endl << endl; //For spacing
|
||||
}
|
||||
|
||||
|
||||
//Do runtimes next
|
||||
outputFile << "** Runtimes **";
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
if(storedRuntime[i].find("Infinite loop suspected") != std::string::npos || storedRuntime[i].find("Maximum recursion level reached") != std::string::npos) continue;
|
||||
|
||||
if(numRuntime[i] != 0) outputFile << endl << endl << "The following runtime has occured " << numRuntime[i] << " time(s).\n";
|
||||
if(storedRuntime[i] != "Blank") outputFile << storedRuntime[i] << endl;
|
||||
if(storedProc[i] != "Blank") outputFile << storedProc[i] << endl;
|
||||
if(storedSource[i] != "Blank") outputFile << storedSource[i] << endl;
|
||||
if(storedUsr[i] != "Blank") outputFile << storedUsr[i] << endl;
|
||||
if(storedSrc[i] != "Blank") outputFile << storedSrc[i] << endl;
|
||||
}
|
||||
outputFile.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void sortRuntimes()
|
||||
{
|
||||
string tempRuntime[maxStorage+1];
|
||||
string tempProc[maxStorage+1];
|
||||
string tempSource[maxStorage+1];
|
||||
string tempUsr[maxStorage+1];
|
||||
string tempSrc[maxStorage+1];
|
||||
unsigned int tempNumRuntime[maxStorage+1];
|
||||
unsigned int highestCount = 0; //Used for descending order
|
||||
// int keepLooping = 0;
|
||||
|
||||
//Move all of our data into temporary arrays. Also clear the stored data (not necessary but.. just incase)
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
//Get the largest occurance of a single runtime
|
||||
if(highestCount < numRuntime[i])
|
||||
{
|
||||
highestCount = numRuntime[i];
|
||||
}
|
||||
|
||||
tempRuntime[i] = storedRuntime[i]; storedRuntime[i] = "Blank";
|
||||
tempProc[i] = storedProc[i]; storedProc[i] = "Blank";
|
||||
tempSource[i] = storedSource[i]; storedSource[i] = "Blank";
|
||||
tempUsr[i] = storedUsr[i]; storedUsr[i] = "Blank";
|
||||
tempSrc[i] = storedSrc[i]; storedSrc[i] = "Blank";
|
||||
tempNumRuntime[i] = numRuntime[i]; numRuntime[i] = 0;
|
||||
}
|
||||
|
||||
while(highestCount > 0)
|
||||
{
|
||||
for(int i=0; i <= maxStorage; i++) //For every runtime
|
||||
{
|
||||
if(tempNumRuntime[i] == highestCount) //If the number of occurances of that runtime is equal to our current highest
|
||||
{
|
||||
for(int j=0; j <= maxStorage; j++) //Find the next available slot and store the info
|
||||
{
|
||||
if(storedRuntime[j] == "Blank") //Found an empty spot
|
||||
{
|
||||
storedRuntime[j] = tempRuntime[i];
|
||||
storedProc[j] = tempProc[i];
|
||||
storedSource[j] = tempSource[i];
|
||||
storedUsr[j] = tempUsr[i];
|
||||
storedSrc[j] = tempSrc[i];
|
||||
numRuntime[j] = tempNumRuntime[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
highestCount--; //Lower our 'highest' by one and continue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
char exit; //Used to stop the program from immediatly exiting
|
||||
|
||||
//Start everything fresh. "Blank" should never occur in the runtime logs on its own.
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
storedRuntime[i] = "Blank";
|
||||
storedProc[i] = "Blank";
|
||||
storedSource[i] = "Blank";
|
||||
storedUsr[i] = "Blank";
|
||||
storedSrc[i] = "Blank";
|
||||
numRuntime[i] = 0;
|
||||
|
||||
}
|
||||
|
||||
if(readFromFile())
|
||||
{
|
||||
cout << "Input read successfully!\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Input failed to open, shutting down.\n";
|
||||
cout << "\nEnter any letter to quit.\n";
|
||||
cin >> exit;
|
||||
return 1;
|
||||
}
|
||||
|
||||
sortRuntimes();
|
||||
|
||||
if(writeToFile())
|
||||
{
|
||||
cout << "Output was successful!\n";
|
||||
cout << "\nEnter any letter to quit.\n";
|
||||
cin >> exit;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "The output file could not be opened, shutting down.\n";
|
||||
cout << "\nEnter any letter to quit.\n";
|
||||
cin >> exit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Runtime Condenser by Nodrak
|
||||
* This will sum up identical runtimes into one, giving a total of how many times it occured. The first occurance
|
||||
* of the runtime will log the proc, source, usr and src, the rest will just add to the total. Infinite loops will
|
||||
* also be caught and displayed (if any) above the list of runtimes.
|
||||
*
|
||||
* How to use:
|
||||
* 1) Copy and paste your list of runtimes from Dream Daemon into input.exe
|
||||
* 2) Run RuntimeCondenser.exe
|
||||
* 3) Open output.txt for a condensed report of the runtimes
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
//Make all of these global. It's bad yes, but it's a small program so it really doesn't affect anything.
|
||||
//Because hardcoded numbers are bad :(
|
||||
const unsigned short maxStorage = 99; //100 - 1
|
||||
|
||||
//What we use to read input
|
||||
string currentLine = "Blank";
|
||||
string nextLine = "Blank";
|
||||
|
||||
//Stores lines we want to keep to print out
|
||||
string storedRuntime[maxStorage+1];
|
||||
string storedProc[maxStorage+1];
|
||||
string storedSource[maxStorage+1];
|
||||
string storedUsr[maxStorage+1];
|
||||
string storedSrc[maxStorage+1];
|
||||
|
||||
//Stat tracking stuff for output
|
||||
unsigned int totalRuntimes = 0;
|
||||
unsigned int totalUniqueRuntimes = 0;
|
||||
unsigned int totalInfiniteLoops = 0;
|
||||
unsigned int totalUniqueInfiniteLoops = 0;
|
||||
|
||||
//Misc
|
||||
unsigned int numRuntime[maxStorage+1]; //Number of times a specific runtime has occured
|
||||
bool checkNextLines = false; //Used in case byond has condensed a large number of similar runtimes
|
||||
int storedIterator = 0; //Used to remember where we stored the runtime
|
||||
|
||||
bool readFromFile()
|
||||
{
|
||||
//Open file to read
|
||||
ifstream inputFile("input.txt");
|
||||
|
||||
if(inputFile.is_open())
|
||||
{
|
||||
while(!inputFile.eof()) //Until end of file
|
||||
{
|
||||
//If we've run out of storage
|
||||
if(storedRuntime[maxStorage] != "Blank") break;
|
||||
|
||||
//Update our lines
|
||||
currentLine = nextLine;
|
||||
getline(inputFile, nextLine);
|
||||
|
||||
//After finding a new runtime, check to see if there are extra values to store
|
||||
if(checkNextLines)
|
||||
{
|
||||
//Skip ahead
|
||||
currentLine = nextLine;
|
||||
getline(inputFile, nextLine);
|
||||
|
||||
//If we find this, we have new stuff to store
|
||||
if(nextLine.find("usr:") != std::string::npos)
|
||||
{
|
||||
//Store more info
|
||||
storedSource[storedIterator] = currentLine;
|
||||
storedUsr[storedIterator] = nextLine;
|
||||
|
||||
//Skip ahead again
|
||||
currentLine = nextLine;
|
||||
getline(inputFile, nextLine);
|
||||
|
||||
//Store the last of the info
|
||||
storedSrc[storedIterator] = nextLine;
|
||||
}
|
||||
checkNextLines = false;
|
||||
}
|
||||
|
||||
//Found an infinite loop!
|
||||
if(currentLine.find("Infinite loop suspected") != std::string::npos || currentLine.find("Maximum recursion level reached") != std::string::npos)
|
||||
{
|
||||
totalInfiniteLoops++;
|
||||
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
//We've already encountered this
|
||||
if(currentLine == storedRuntime[i])
|
||||
{
|
||||
numRuntime[i]++;
|
||||
break;
|
||||
}
|
||||
|
||||
//We've never encoutnered this
|
||||
if(storedRuntime[i] == "Blank")
|
||||
{
|
||||
storedRuntime[i] = currentLine;
|
||||
currentLine = nextLine;
|
||||
getline(inputFile, nextLine); //Skip the "if this is not an infinite loop" line
|
||||
storedProc[i] = nextLine;
|
||||
numRuntime[i] = 1;
|
||||
checkNextLines = true;
|
||||
storedIterator = i;
|
||||
totalUniqueInfiniteLoops++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Found a runtime!
|
||||
else if(currentLine.find("runtime error:") != std::string::npos)
|
||||
{
|
||||
totalRuntimes++;
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
//We've already encountered this
|
||||
if(currentLine == storedRuntime[i])
|
||||
{
|
||||
numRuntime[i]++;
|
||||
break;
|
||||
}
|
||||
|
||||
//We've never encoutnered this
|
||||
if(storedRuntime[i] == "Blank")
|
||||
{
|
||||
storedRuntime[i] = currentLine;
|
||||
storedProc[i] = nextLine;
|
||||
numRuntime[i] = 1;
|
||||
checkNextLines = true;
|
||||
storedIterator = i;
|
||||
totalUniqueRuntimes++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeToFile()
|
||||
{
|
||||
//Open and clear the file
|
||||
ofstream outputFile("Output.txt", ios::trunc);
|
||||
|
||||
if(outputFile.is_open())
|
||||
{
|
||||
outputFile << "Note: The proc name, source file, src and usr are all from the FIRST of the identical runtimes. Everything else is cropped.\n\n";
|
||||
if(totalUniqueInfiniteLoops > 0)
|
||||
{
|
||||
outputFile << "Total unique infinite loops: " << totalUniqueInfiniteLoops << endl;
|
||||
}
|
||||
if(totalInfiniteLoops > 0)
|
||||
{
|
||||
outputFile << "Total infinite loops: " << totalInfiniteLoops << endl;
|
||||
}
|
||||
outputFile << "Total unique runtimes: " << totalUniqueRuntimes << endl;
|
||||
outputFile << "Total runtimes: " << totalRuntimes << endl << endl;
|
||||
|
||||
//Display a warning if we've hit the maximum space we've allocated for storage
|
||||
if(totalUniqueRuntimes + totalUniqueInfiniteLoops >= maxStorage)
|
||||
{
|
||||
outputFile << "Warning: The maximum number of unique runtimes has been hit. If there were more, they have been cropped out.\n\n";
|
||||
}
|
||||
|
||||
|
||||
//If we have infinite loops, display them first.
|
||||
if(totalInfiniteLoops > 0)
|
||||
{
|
||||
outputFile << "** Infinite loops **";
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
if(storedRuntime[i].find("Infinite loop suspected") != std::string::npos || storedRuntime[i].find("Maximum recursion level reached") != std::string::npos)
|
||||
{
|
||||
if(numRuntime[i] != 0) outputFile << endl << endl << "The following infinite loop has occured " << numRuntime[i] << " time(s).\n";
|
||||
if(storedRuntime[i] != "Blank") outputFile << storedRuntime[i] << endl;
|
||||
if(storedProc[i] != "Blank") outputFile << storedProc[i] << endl;
|
||||
if(storedSource[i] != "Blank") outputFile << storedSource[i] << endl;
|
||||
if(storedUsr[i] != "Blank") outputFile << storedUsr[i] << endl;
|
||||
if(storedSrc[i] != "Blank") outputFile << storedSrc[i] << endl;
|
||||
}
|
||||
}
|
||||
outputFile << endl << endl; //For spacing
|
||||
}
|
||||
|
||||
|
||||
//Do runtimes next
|
||||
outputFile << "** Runtimes **";
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
if(storedRuntime[i].find("Infinite loop suspected") != std::string::npos || storedRuntime[i].find("Maximum recursion level reached") != std::string::npos) continue;
|
||||
|
||||
if(numRuntime[i] != 0) outputFile << endl << endl << "The following runtime has occured " << numRuntime[i] << " time(s).\n";
|
||||
if(storedRuntime[i] != "Blank") outputFile << storedRuntime[i] << endl;
|
||||
if(storedProc[i] != "Blank") outputFile << storedProc[i] << endl;
|
||||
if(storedSource[i] != "Blank") outputFile << storedSource[i] << endl;
|
||||
if(storedUsr[i] != "Blank") outputFile << storedUsr[i] << endl;
|
||||
if(storedSrc[i] != "Blank") outputFile << storedSrc[i] << endl;
|
||||
}
|
||||
outputFile.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void sortRuntimes()
|
||||
{
|
||||
string tempRuntime[maxStorage+1];
|
||||
string tempProc[maxStorage+1];
|
||||
string tempSource[maxStorage+1];
|
||||
string tempUsr[maxStorage+1];
|
||||
string tempSrc[maxStorage+1];
|
||||
unsigned int tempNumRuntime[maxStorage+1];
|
||||
unsigned int highestCount = 0; //Used for descending order
|
||||
// int keepLooping = 0;
|
||||
|
||||
//Move all of our data into temporary arrays. Also clear the stored data (not necessary but.. just incase)
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
//Get the largest occurance of a single runtime
|
||||
if(highestCount < numRuntime[i])
|
||||
{
|
||||
highestCount = numRuntime[i];
|
||||
}
|
||||
|
||||
tempRuntime[i] = storedRuntime[i]; storedRuntime[i] = "Blank";
|
||||
tempProc[i] = storedProc[i]; storedProc[i] = "Blank";
|
||||
tempSource[i] = storedSource[i]; storedSource[i] = "Blank";
|
||||
tempUsr[i] = storedUsr[i]; storedUsr[i] = "Blank";
|
||||
tempSrc[i] = storedSrc[i]; storedSrc[i] = "Blank";
|
||||
tempNumRuntime[i] = numRuntime[i]; numRuntime[i] = 0;
|
||||
}
|
||||
|
||||
while(highestCount > 0)
|
||||
{
|
||||
for(int i=0; i <= maxStorage; i++) //For every runtime
|
||||
{
|
||||
if(tempNumRuntime[i] == highestCount) //If the number of occurances of that runtime is equal to our current highest
|
||||
{
|
||||
for(int j=0; j <= maxStorage; j++) //Find the next available slot and store the info
|
||||
{
|
||||
if(storedRuntime[j] == "Blank") //Found an empty spot
|
||||
{
|
||||
storedRuntime[j] = tempRuntime[i];
|
||||
storedProc[j] = tempProc[i];
|
||||
storedSource[j] = tempSource[i];
|
||||
storedUsr[j] = tempUsr[i];
|
||||
storedSrc[j] = tempSrc[i];
|
||||
numRuntime[j] = tempNumRuntime[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
highestCount--; //Lower our 'highest' by one and continue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
char exit; //Used to stop the program from immediatly exiting
|
||||
|
||||
//Start everything fresh. "Blank" should never occur in the runtime logs on its own.
|
||||
for(int i=0; i <= maxStorage; i++)
|
||||
{
|
||||
storedRuntime[i] = "Blank";
|
||||
storedProc[i] = "Blank";
|
||||
storedSource[i] = "Blank";
|
||||
storedUsr[i] = "Blank";
|
||||
storedSrc[i] = "Blank";
|
||||
numRuntime[i] = 0;
|
||||
|
||||
}
|
||||
|
||||
if(readFromFile())
|
||||
{
|
||||
cout << "Input read successfully!\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Input failed to open, shutting down.\n";
|
||||
cout << "\nEnter any letter to quit.\n";
|
||||
cin >> exit;
|
||||
return 1;
|
||||
}
|
||||
|
||||
sortRuntimes();
|
||||
|
||||
if(writeToFile())
|
||||
{
|
||||
cout << "Output was successful!\n";
|
||||
cout << "\nEnter any letter to quit.\n";
|
||||
cin >> exit;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "The output file could not be opened, shutting down.\n";
|
||||
cout << "\nEnter any letter to quit.\n";
|
||||
cin >> exit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,190 +1,190 @@
|
||||
Note: The proc name, source file, src and usr are all from the FIRST of the identical runtimes. Everything else is cropped.
|
||||
|
||||
Total unique runtimes: 25
|
||||
Total runtimes: 767
|
||||
|
||||
** Runtimes **
|
||||
|
||||
The following runtime has occured 269 time(s).
|
||||
runtime error: Cannot read null.viruses
|
||||
proc name: cure (/datum/disease/proc/cure)
|
||||
source file: disease.dm,156
|
||||
usr: null
|
||||
src: Space Retrovirus (/datum/disease/dnaspread)
|
||||
|
||||
|
||||
The following runtime has occured 199 time(s).
|
||||
runtime error: Cannot read null.has_gravity
|
||||
proc name: throw at (/atom/movable/proc/throw_at)
|
||||
source file: throwing.dm,194
|
||||
usr: Reese Marcotte (/mob/living/carbon/human)
|
||||
src: Reese Marcotte (/mob/living/carbon/human)
|
||||
|
||||
|
||||
The following runtime has occured 165 time(s).
|
||||
runtime error: Cannot read null.slot_flags
|
||||
proc name: db click (/mob/living/carbon/human/db_click)
|
||||
source file: inventory.dm,1083
|
||||
usr: Puke Chunks (/mob/living/carbon/human)
|
||||
src: Puke Chunks (/mob/living/carbon/human)
|
||||
|
||||
|
||||
The following runtime has occured 25 time(s).
|
||||
runtime error: Cannot read null.flags
|
||||
proc name: relaymove (/obj/effect/dummy/spell_jaunt/relaymove)
|
||||
|
||||
|
||||
The following runtime has occured 24 time(s).
|
||||
runtime error: Cannot read null.len
|
||||
proc name: mergeRecordLists (/proc/mergeRecordLists)
|
||||
source file: helpers.dm,260
|
||||
usr: Wintermute (/mob/living/silicon/ai)
|
||||
src: null
|
||||
|
||||
|
||||
The following runtime has occured 20 time(s).
|
||||
runtime error: Cannot read null.total_volume
|
||||
proc name: attackby (/obj/machinery/reagentgrinder/attackby)
|
||||
source file: Chemistry-Machinery.dm,751
|
||||
usr: Reese Marcotte (/mob/living/carbon/human)
|
||||
src: All-In-One Grinder (/obj/machinery/reagentgrinder)
|
||||
|
||||
|
||||
The following runtime has occured 16 time(s).
|
||||
runtime error: Cannot read null.broadcasting
|
||||
proc name: radio menu (/mob/living/silicon/robot/proc/radio_menu)
|
||||
source file: robot.dm,857
|
||||
usr: Engineering Cyborg -432 (/mob/living/silicon/robot)
|
||||
src: Engineering Cyborg -432 (/mob/living/silicon/robot)
|
||||
|
||||
|
||||
The following runtime has occured 7 time(s).
|
||||
runtime error: unexpected stat
|
||||
proc name: Stat (/mob/living/silicon/robot/Stat)
|
||||
source file: robot.dm,227
|
||||
usr: Michigan Slim (/mob/living/carbon/human)
|
||||
src: Engineering Cyborg -133 (/mob/living/silicon/robot)
|
||||
|
||||
|
||||
The following runtime has occured 7 time(s).
|
||||
runtime error: Cannot read null.current
|
||||
proc name: check completion (/datum/objective/download/check_completion)
|
||||
source file: objective.dm,411
|
||||
usr: null
|
||||
src: /datum/objective/download (/datum/objective/download)
|
||||
|
||||
|
||||
The following runtime has occured 6 time(s).
|
||||
runtime error: Cannot create objects of type null.
|
||||
proc name: Topic (/obj/machinery/computer/rdconsole/Topic)
|
||||
source file: rdconsole.dm,381
|
||||
usr: Matthew Hoff (/mob/living/carbon/human)
|
||||
src: Core R&D Console (/obj/machinery/computer/rdconsole/core)
|
||||
|
||||
|
||||
The following runtime has occured 6 time(s).
|
||||
runtime error: Cannot read null.fields
|
||||
proc name: mergeRecordLists (/proc/mergeRecordLists)
|
||||
source file: helpers.dm,263
|
||||
usr: Wintermute (/mob/living/silicon/ai)
|
||||
src: null
|
||||
|
||||
|
||||
The following runtime has occured 3 time(s).
|
||||
runtime error: undefined variable /client/var/loc
|
||||
proc name: get turf (/proc/get_turf)
|
||||
source file: helper_procs.dm,38
|
||||
usr: the ghost (/mob/dead/observer)
|
||||
src: null
|
||||
|
||||
|
||||
The following runtime has occured 3 time(s).
|
||||
runtime error: Cannot read null.nodes
|
||||
proc name: merge powernets (/datum/powernet/proc/merge_powernets)
|
||||
source file: power.dm,401
|
||||
usr: Darin Keppel (/mob/living/carbon/human)
|
||||
src: /datum/powernet (/datum/powernet)
|
||||
|
||||
|
||||
The following runtime has occured 3 time(s).
|
||||
runtime error: Cannot read null.reagents
|
||||
proc name: fire syringe (/obj/item/weapon/gun/syringe/proc/fire_syringe)
|
||||
|
||||
|
||||
The following runtime has occured 2 time(s).
|
||||
runtime error: undefined proc or verb /obj/machinery/space_heater/attack().
|
||||
|
||||
|
||||
|
||||
The following runtime has occured 2 time(s).
|
||||
runtime error: list index out of bounds
|
||||
proc name: mergeConnectedNetworksOnTurf (/obj/structure/cable/proc/mergeConnectedNetworksOnTurf)
|
||||
source file: cable.dm,520
|
||||
usr: Josue Sandford (/mob/living/carbon/human)
|
||||
src: the power cable (/obj/structure/cable)
|
||||
|
||||
|
||||
The following runtime has occured 2 time(s).
|
||||
runtime error: Cannot read null.loc
|
||||
proc name: Life (/mob/living/simple_animal/corgi/Ian/Life)
|
||||
source file: corgi.dm,304
|
||||
usr: null
|
||||
src: Captain Ian (/mob/living/simple_animal/corgi/Ian)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: undefined proc or verb /obj/machinery/portable_atmospherics/canister/toxins/attack().
|
||||
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: undefined variable /datum/preferences/var/fields
|
||||
proc name: Topic (/obj/machinery/computer/cloning/Topic)
|
||||
source file: cloning.dm,370
|
||||
usr: Logan Graves (/mob/living/carbon/human)
|
||||
src: Cloning console (/obj/machinery/computer/cloning)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: undefined variable /turf/simulated/floor/plating/var/mineral
|
||||
proc name: attackby (/turf/simulated/wall/attackby)
|
||||
source file: turf.dm,600
|
||||
usr: Monte Smail (/mob/living/carbon/human)
|
||||
src: the plating (176,172,5) (/turf/simulated/floor/plating)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot read null.blood_DNA
|
||||
proc name: update inv w uniform (/mob/living/carbon/human/update_inv_w_uniform)
|
||||
source file: update_icons.dm,372
|
||||
usr: null
|
||||
src: Chip Harshman (/mob/living/carbon/human)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot execute null.dropped().
|
||||
proc name: drop l hand (/mob/proc/drop_l_hand)
|
||||
source file: inventory.dm,104
|
||||
usr: Jeb Stone (/mob/living/carbon/human)
|
||||
src: Jeb Stone (/mob/living/carbon/human)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot read null.w_class
|
||||
proc name: attackby (/obj/item/weapon/storage/attackby)
|
||||
source file: storage.dm,187
|
||||
usr: Samuel York (/mob/living/carbon/human)
|
||||
src: the backpack (/obj/item/weapon/storage/backpack)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot read null.amount
|
||||
proc name: attackby (/obj/machinery/constructable_frame/machine_frame/attackby)
|
||||
source file: constructable_frame.dm,27
|
||||
usr: Quinton Bould (/mob/living/carbon/human)
|
||||
src: the machine frame (/obj/machinery/constructable_frame/machine_frame)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot modify null.status.
|
||||
proc name: death (/mob/living/silicon/robot/death)
|
||||
Note: The proc name, source file, src and usr are all from the FIRST of the identical runtimes. Everything else is cropped.
|
||||
|
||||
Total unique runtimes: 25
|
||||
Total runtimes: 767
|
||||
|
||||
** Runtimes **
|
||||
|
||||
The following runtime has occured 269 time(s).
|
||||
runtime error: Cannot read null.viruses
|
||||
proc name: cure (/datum/disease/proc/cure)
|
||||
source file: disease.dm,156
|
||||
usr: null
|
||||
src: Space Retrovirus (/datum/disease/dnaspread)
|
||||
|
||||
|
||||
The following runtime has occured 199 time(s).
|
||||
runtime error: Cannot read null.has_gravity
|
||||
proc name: throw at (/atom/movable/proc/throw_at)
|
||||
source file: throwing.dm,194
|
||||
usr: Reese Marcotte (/mob/living/carbon/human)
|
||||
src: Reese Marcotte (/mob/living/carbon/human)
|
||||
|
||||
|
||||
The following runtime has occured 165 time(s).
|
||||
runtime error: Cannot read null.slot_flags
|
||||
proc name: db click (/mob/living/carbon/human/db_click)
|
||||
source file: inventory.dm,1083
|
||||
usr: Puke Chunks (/mob/living/carbon/human)
|
||||
src: Puke Chunks (/mob/living/carbon/human)
|
||||
|
||||
|
||||
The following runtime has occured 25 time(s).
|
||||
runtime error: Cannot read null.flags
|
||||
proc name: relaymove (/obj/effect/dummy/spell_jaunt/relaymove)
|
||||
|
||||
|
||||
The following runtime has occured 24 time(s).
|
||||
runtime error: Cannot read null.len
|
||||
proc name: mergeRecordLists (/proc/mergeRecordLists)
|
||||
source file: helpers.dm,260
|
||||
usr: Wintermute (/mob/living/silicon/ai)
|
||||
src: null
|
||||
|
||||
|
||||
The following runtime has occured 20 time(s).
|
||||
runtime error: Cannot read null.total_volume
|
||||
proc name: attackby (/obj/machinery/reagentgrinder/attackby)
|
||||
source file: Chemistry-Machinery.dm,751
|
||||
usr: Reese Marcotte (/mob/living/carbon/human)
|
||||
src: All-In-One Grinder (/obj/machinery/reagentgrinder)
|
||||
|
||||
|
||||
The following runtime has occured 16 time(s).
|
||||
runtime error: Cannot read null.broadcasting
|
||||
proc name: radio menu (/mob/living/silicon/robot/proc/radio_menu)
|
||||
source file: robot.dm,857
|
||||
usr: Engineering Cyborg -432 (/mob/living/silicon/robot)
|
||||
src: Engineering Cyborg -432 (/mob/living/silicon/robot)
|
||||
|
||||
|
||||
The following runtime has occured 7 time(s).
|
||||
runtime error: unexpected stat
|
||||
proc name: Stat (/mob/living/silicon/robot/Stat)
|
||||
source file: robot.dm,227
|
||||
usr: Michigan Slim (/mob/living/carbon/human)
|
||||
src: Engineering Cyborg -133 (/mob/living/silicon/robot)
|
||||
|
||||
|
||||
The following runtime has occured 7 time(s).
|
||||
runtime error: Cannot read null.current
|
||||
proc name: check completion (/datum/objective/download/check_completion)
|
||||
source file: objective.dm,411
|
||||
usr: null
|
||||
src: /datum/objective/download (/datum/objective/download)
|
||||
|
||||
|
||||
The following runtime has occured 6 time(s).
|
||||
runtime error: Cannot create objects of type null.
|
||||
proc name: Topic (/obj/machinery/computer/rdconsole/Topic)
|
||||
source file: rdconsole.dm,381
|
||||
usr: Matthew Hoff (/mob/living/carbon/human)
|
||||
src: Core R&D Console (/obj/machinery/computer/rdconsole/core)
|
||||
|
||||
|
||||
The following runtime has occured 6 time(s).
|
||||
runtime error: Cannot read null.fields
|
||||
proc name: mergeRecordLists (/proc/mergeRecordLists)
|
||||
source file: helpers.dm,263
|
||||
usr: Wintermute (/mob/living/silicon/ai)
|
||||
src: null
|
||||
|
||||
|
||||
The following runtime has occured 3 time(s).
|
||||
runtime error: undefined variable /client/var/loc
|
||||
proc name: get turf (/proc/get_turf)
|
||||
source file: helper_procs.dm,38
|
||||
usr: the ghost (/mob/dead/observer)
|
||||
src: null
|
||||
|
||||
|
||||
The following runtime has occured 3 time(s).
|
||||
runtime error: Cannot read null.nodes
|
||||
proc name: merge powernets (/datum/powernet/proc/merge_powernets)
|
||||
source file: power.dm,401
|
||||
usr: Darin Keppel (/mob/living/carbon/human)
|
||||
src: /datum/powernet (/datum/powernet)
|
||||
|
||||
|
||||
The following runtime has occured 3 time(s).
|
||||
runtime error: Cannot read null.reagents
|
||||
proc name: fire syringe (/obj/item/weapon/gun/syringe/proc/fire_syringe)
|
||||
|
||||
|
||||
The following runtime has occured 2 time(s).
|
||||
runtime error: undefined proc or verb /obj/machinery/space_heater/attack().
|
||||
|
||||
|
||||
|
||||
The following runtime has occured 2 time(s).
|
||||
runtime error: list index out of bounds
|
||||
proc name: mergeConnectedNetworksOnTurf (/obj/structure/cable/proc/mergeConnectedNetworksOnTurf)
|
||||
source file: cable.dm,520
|
||||
usr: Josue Sandford (/mob/living/carbon/human)
|
||||
src: the power cable (/obj/structure/cable)
|
||||
|
||||
|
||||
The following runtime has occured 2 time(s).
|
||||
runtime error: Cannot read null.loc
|
||||
proc name: Life (/mob/living/simple_animal/corgi/Ian/Life)
|
||||
source file: corgi.dm,304
|
||||
usr: null
|
||||
src: Captain Ian (/mob/living/simple_animal/corgi/Ian)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: undefined proc or verb /obj/machinery/portable_atmospherics/canister/toxins/attack().
|
||||
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: undefined variable /datum/preferences/var/fields
|
||||
proc name: Topic (/obj/machinery/computer/cloning/Topic)
|
||||
source file: cloning.dm,370
|
||||
usr: Logan Graves (/mob/living/carbon/human)
|
||||
src: Cloning console (/obj/machinery/computer/cloning)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: undefined variable /turf/simulated/floor/plating/var/mineral
|
||||
proc name: attackby (/turf/simulated/wall/attackby)
|
||||
source file: turf.dm,600
|
||||
usr: Monte Smail (/mob/living/carbon/human)
|
||||
src: the plating (176,172,5) (/turf/simulated/floor/plating)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot read null.blood_DNA
|
||||
proc name: update inv w uniform (/mob/living/carbon/human/update_inv_w_uniform)
|
||||
source file: update_icons.dm,372
|
||||
usr: null
|
||||
src: Chip Harshman (/mob/living/carbon/human)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot execute null.dropped().
|
||||
proc name: drop l hand (/mob/proc/drop_l_hand)
|
||||
source file: inventory.dm,104
|
||||
usr: Jeb Stone (/mob/living/carbon/human)
|
||||
src: Jeb Stone (/mob/living/carbon/human)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot read null.w_class
|
||||
proc name: attackby (/obj/item/weapon/storage/attackby)
|
||||
source file: storage.dm,187
|
||||
usr: Samuel York (/mob/living/carbon/human)
|
||||
src: the backpack (/obj/item/weapon/storage/backpack)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot read null.amount
|
||||
proc name: attackby (/obj/machinery/constructable_frame/machine_frame/attackby)
|
||||
source file: constructable_frame.dm,27
|
||||
usr: Quinton Bould (/mob/living/carbon/human)
|
||||
src: the machine frame (/obj/machinery/constructable_frame/machine_frame)
|
||||
|
||||
|
||||
The following runtime has occured 1 time(s).
|
||||
runtime error: Cannot modify null.status.
|
||||
proc name: death (/mob/living/silicon/robot/death)
|
||||
|
||||
@@ -1,90 +1,90 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import re, os, sys, fnmatch
|
||||
|
||||
|
||||
# Regex pattern to extract the directory path in a #define FILE_DIR
|
||||
filedir_pattern = re.compile(r'^#define\s*FILE_DIR\s*"(.*?)"')
|
||||
|
||||
# Regex pattern to extract any single quoted piece of text. This can also
|
||||
# match single quoted strings inside of double quotes, which is part of a
|
||||
# regular text string and should not be replaced. The replacement function
|
||||
# however will any match that doesn't appear to be a filename so these
|
||||
# extra matches should not be a problem.
|
||||
rename_pattern = re.compile(r"'(.+?)'")
|
||||
|
||||
# Only filenames matching this pattern will have their resources renamed
|
||||
source_pattern = re.compile(r"^.*?\.(dm|dmm)$")
|
||||
|
||||
# Open the .dme file and return a list of all FILE_DIR paths in it
|
||||
def read_filedirs(filename):
|
||||
result = []
|
||||
with open(filename, "rt") as dme_file:
|
||||
# Read each line from the file and check for regex pattern match
|
||||
for row in dme_file:
|
||||
match = filedir_pattern.match(row)
|
||||
if match:
|
||||
result.append(match.group(1))
|
||||
return result
|
||||
|
||||
# Search through a list of directories, and build a dictionary which
|
||||
# maps every file to its full pathname (relative to the .dme file)
|
||||
# If the same filename appears in more than one directory, the earlier
|
||||
# directory in the list takes preference.
|
||||
def index_files(file_dirs):
|
||||
result = {}
|
||||
|
||||
# Reverse the directory list so the earlier directories take precedence
|
||||
# by replacing the previously indexed file of the same name
|
||||
for directory in reversed(file_dirs):
|
||||
for name in os.listdir(directory):
|
||||
# Replace backslash path separators on Windows with forward slash
|
||||
# Force "name" to lowercase when used as a key since BYOND resource
|
||||
# names are case insensitive, even on Linux.
|
||||
if name.find(".") == -1:
|
||||
continue
|
||||
result[name.lower()] = directory.replace('\\', '/') + '/' + name
|
||||
|
||||
return result
|
||||
|
||||
# Recursively search for every .dm/.dmm file in the .dme file directory. For
|
||||
# each file, search it for any resource names in single quotes, and replace
|
||||
# them with the full path previously found by index_files()
|
||||
def rewrite_sources(resources):
|
||||
# Create a closure for the regex replacement function to capture the
|
||||
# resources dictionary which can't be passed directly to this function
|
||||
def replace_func(name):
|
||||
key = name.group(1).lower()
|
||||
if key in resources:
|
||||
replacement = resources[key]
|
||||
else:
|
||||
replacement = name.group(1)
|
||||
return "'" + replacement + "'"
|
||||
|
||||
# Search recursively for all .dm and .dmm files
|
||||
for (dirpath, dirs, files) in os.walk("."):
|
||||
for name in files:
|
||||
if source_pattern.match(name):
|
||||
path = dirpath + '/' + name
|
||||
source_file = open(path, "rt")
|
||||
output_file = open(path + ".tmp", "wt")
|
||||
|
||||
# Read file one line at a time and perform replacement of all
|
||||
# single quoted resource names with the fullpath to that resource
|
||||
# file. Write the updated text back out to a temporary file.
|
||||
for row in source_file:
|
||||
row = rename_pattern.sub(replace_func, row)
|
||||
output_file.write(row)
|
||||
|
||||
output_file.close()
|
||||
source_file.close()
|
||||
|
||||
# Delete original source file and replace with the temporary
|
||||
# output. On Windows, an atomic rename() operation is not
|
||||
# possible like it is under POSIX.
|
||||
os.remove(path)
|
||||
os.rename(path + ".tmp", path)
|
||||
|
||||
dirs = read_filedirs("vgstation13.dme");
|
||||
resources = index_files(dirs)
|
||||
rewrite_sources(resources)
|
||||
#!/usr/bin/env python
|
||||
|
||||
import re, os, sys, fnmatch
|
||||
|
||||
|
||||
# Regex pattern to extract the directory path in a #define FILE_DIR
|
||||
filedir_pattern = re.compile(r'^#define\s*FILE_DIR\s*"(.*?)"')
|
||||
|
||||
# Regex pattern to extract any single quoted piece of text. This can also
|
||||
# match single quoted strings inside of double quotes, which is part of a
|
||||
# regular text string and should not be replaced. The replacement function
|
||||
# however will any match that doesn't appear to be a filename so these
|
||||
# extra matches should not be a problem.
|
||||
rename_pattern = re.compile(r"'(.+?)'")
|
||||
|
||||
# Only filenames matching this pattern will have their resources renamed
|
||||
source_pattern = re.compile(r"^.*?\.(dm|dmm)$")
|
||||
|
||||
# Open the .dme file and return a list of all FILE_DIR paths in it
|
||||
def read_filedirs(filename):
|
||||
result = []
|
||||
with open(filename, "rt") as dme_file:
|
||||
# Read each line from the file and check for regex pattern match
|
||||
for row in dme_file:
|
||||
match = filedir_pattern.match(row)
|
||||
if match:
|
||||
result.append(match.group(1))
|
||||
return result
|
||||
|
||||
# Search through a list of directories, and build a dictionary which
|
||||
# maps every file to its full pathname (relative to the .dme file)
|
||||
# If the same filename appears in more than one directory, the earlier
|
||||
# directory in the list takes preference.
|
||||
def index_files(file_dirs):
|
||||
result = {}
|
||||
|
||||
# Reverse the directory list so the earlier directories take precedence
|
||||
# by replacing the previously indexed file of the same name
|
||||
for directory in reversed(file_dirs):
|
||||
for name in os.listdir(directory):
|
||||
# Replace backslash path separators on Windows with forward slash
|
||||
# Force "name" to lowercase when used as a key since BYOND resource
|
||||
# names are case insensitive, even on Linux.
|
||||
if name.find(".") == -1:
|
||||
continue
|
||||
result[name.lower()] = directory.replace('\\', '/') + '/' + name
|
||||
|
||||
return result
|
||||
|
||||
# Recursively search for every .dm/.dmm file in the .dme file directory. For
|
||||
# each file, search it for any resource names in single quotes, and replace
|
||||
# them with the full path previously found by index_files()
|
||||
def rewrite_sources(resources):
|
||||
# Create a closure for the regex replacement function to capture the
|
||||
# resources dictionary which can't be passed directly to this function
|
||||
def replace_func(name):
|
||||
key = name.group(1).lower()
|
||||
if key in resources:
|
||||
replacement = resources[key]
|
||||
else:
|
||||
replacement = name.group(1)
|
||||
return "'" + replacement + "'"
|
||||
|
||||
# Search recursively for all .dm and .dmm files
|
||||
for (dirpath, dirs, files) in os.walk("."):
|
||||
for name in files:
|
||||
if source_pattern.match(name):
|
||||
path = dirpath + '/' + name
|
||||
source_file = open(path, "rt")
|
||||
output_file = open(path + ".tmp", "wt")
|
||||
|
||||
# Read file one line at a time and perform replacement of all
|
||||
# single quoted resource names with the fullpath to that resource
|
||||
# file. Write the updated text back out to a temporary file.
|
||||
for row in source_file:
|
||||
row = rename_pattern.sub(replace_func, row)
|
||||
output_file.write(row)
|
||||
|
||||
output_file.close()
|
||||
source_file.close()
|
||||
|
||||
# Delete original source file and replace with the temporary
|
||||
# output. On Windows, an atomic rename() operation is not
|
||||
# possible like it is under POSIX.
|
||||
os.remove(path)
|
||||
os.rename(path + ".tmp", path)
|
||||
|
||||
dirs = read_filedirs("vgstation13.dme");
|
||||
resources = index_files(dirs)
|
||||
rewrite_sources(resources)
|
||||
|
||||
Reference in New Issue
Block a user