Skip to content

Commit

Permalink
Handle max=v and x=max(v) correctly.
Browse files Browse the repository at this point in the history
Fix V:1 not being usable as a keyword.
  • Loading branch information
greensnark committed Dec 16, 2012
1 parent 2214fc1 commit f025e65
Show file tree
Hide file tree
Showing 20 changed files with 127 additions and 37 deletions.
1 change: 1 addition & 0 deletions Henzell/Cmd.pm
Expand Up @@ -46,6 +46,7 @@ sub execute_cmd($$) {
if (!$script) {
return (1, "Command not found: $cmd", $cmd);
}

my $executable_command =
"./commands/$script \Q$target\E \Q$nick\E \Q$cmdline\E ''";
my $output = qx/$executable_command 2>&1/;
Expand Down
9 changes: 5 additions & 4 deletions config/crawl-data.yml
Expand Up @@ -583,6 +583,11 @@ type-categories:
D: D
'!': '!'

column-substitutes:
ordered:
v: vnum
cv: cvnum

##
# Field type suffixes:
# - I (integer)
Expand Down Expand Up @@ -698,10 +703,6 @@ milestone-fields-with-type:
- oplace^
- tiles!

derived-fields:
v: vnum
cv: cvnum

milestone-verb-mappings:
unique: uniq
enter: br.enter
Expand Down
4 changes: 2 additions & 2 deletions docs/listgame.txt
Expand Up @@ -699,10 +699,10 @@ vmsg:
Verbose game end message. Usually identical to tmsg.

alpha:
"y" if the game is an alpha/development version, empty otherwise.
true if the game is an alpha/development version, false otherwise.

tiles:
"y" if the game is in webtiles, empty otherwise.
true if the game is in webtiles, false otherwise.

map:
The name of the map/vault the player was in at end of game. Example:
Expand Down
1 change: 1 addition & 0 deletions runcmd.pl
Expand Up @@ -15,6 +15,7 @@
sub runcmd($) {
chomp(my $cmd = shift);
my $nick;
return unless $cmd =~ /\S/;
if ($cmd =~ /^(\w+): (.*)/) {
$nick = $1;
$cmd = $2;
Expand Down
4 changes: 3 additions & 1 deletion src/crawl/branch_set.rb
Expand Up @@ -2,13 +2,14 @@

module Crawl
class BranchSet
def initialize(branches)
def initialize(branches, place_fixups)
@branches = branches.map { |br|
Crawl::Branch.new(br)
}
@branch_map = Hash[ @branches.map { |br|
[br.name.downcase, br]
} ]
@place_fixups = place_fixups
end

def [](name)
Expand All @@ -21,6 +22,7 @@ def deep?(name)
end

def branch?(keyword)
keyword = @place_fixups.fixup(keyword)[0]
if keyword =~ /^([a-z]+):/i
self[$1]
else
Expand Down
24 changes: 6 additions & 18 deletions src/query/query_expr_parser.rb
Expand Up @@ -171,24 +171,12 @@ def query_field(field, op, val)
val = CLASS_EXPANSIONS[val.downcase] || val
end

if field === ['place', 'oplace'] && op === ['=', '!=', '=~', '!~'] then
place_fixups = CFG['place-fixups']
for place_fixup_match in place_fixups.keys do
regex = %r/#{place_fixup_match}/i
if val =~ regex then
replacement = place_fixups[place_fixup_match]
replacement = [replacement] unless replacement.is_a?(Array)
values = replacement.map { |r|
val.sub(regex, r.sub(%r/\$(\d)/, '\\\1'))
}
inclusive = op.to_s.index('=') == 0
clause = QueryStruct.new(inclusive ? 'OR' : 'AND')
for value in values do
clause << field_pred(value, op, field)
end
return clause
end
end
if field === ['place', 'oplace'] && op.equality? then
fixed_up_places = PLACE_FIXUPS.fixup(val)
return QueryStruct.new(op.equal? ? 'OR' : 'AND',
*fixed_up_places.map { |place|
field_pred(place, op, field)
})
end

if field === 'when'
Expand Down
1 change: 1 addition & 0 deletions src/query/sort.rb
Expand Up @@ -12,6 +12,7 @@ def initialize(field, direction='DESC')
raise "Bad sort direction: #{direction}"
end
@field = field
@field.bind_ordered_column!
@direction = direction
end

Expand Down
45 changes: 45 additions & 0 deletions src/sql/aggregate_expression.rb
@@ -0,0 +1,45 @@
module Sql
class AggregateExpression
def self.aggregate_sql(table_set, expr)
return expr.to_sql unless expr.field
self.new(table_set, expr).to_sql
end

attr_reader :table_set, :expr, :column

def initialize(table_set, expr)
@table_set = table_set
@expr = expr
@column = @expr.column
STDERR.puts("column name: #{@column.name}, expr: #{@expr.expr}")
end

def to_sql
return version_maxmin_sql if version_column? && max_min_expr?
@expr.to_sql
end

def version_column?
@column.name == 'v' || @column.name == 'cv'
end

def max_min_expr?
@expr.expr =~ /^(?:max|min)/i
end

private
def version_maxmin_sql
field = @expr.field.field
original_sql_field_name = field.sql_column_name
reference_table = Sql::QueryTable.table(@column.lookup_table)
@table_set.resolve!(reference_table, true)
field.name = field.name + 'num'
key_field_sql = @expr.expr
sql = ("(SELECT #{original_sql_field_name} " +
"FROM #{reference_table.to_sql} WHERE " +
"#{reference_table.field_sql(field)} = #{key_field_sql})")
sql = "#{sql} AS #{@expr.calias}" if @expr.calias
sql
end
end
end
6 changes: 4 additions & 2 deletions src/sql/column.rb
Expand Up @@ -7,11 +7,13 @@ module Sql
class Column
include TypePredicates

attr_reader :decorated_name
attr_reader :decorated_name, :ordered_column_alias

def initialize(config, decorated_name)
def initialize(config, decorated_name, alias_map)
@config = config
@decorated_name = decorated_name
@ordered_column_alias =
alias_map && alias_map['ordered'] && alias_map['ordered'][self.name]
end

def to_s
Expand Down
4 changes: 2 additions & 2 deletions src/sql/column_list.rb
Expand Up @@ -2,11 +2,11 @@

module Sql
class ColumnList
def initialize(config, column_list)
def initialize(config, column_list, column_alias_map)
@config = config
@column_list = column_list || []
@columns = @column_list.map { |column_config|
Sql::Column.new(config, column_config)
Sql::Column.new(config, column_config, column_alias_map)
}
add_derived_columns
end
Expand Down
14 changes: 11 additions & 3 deletions src/sql/config.rb
Expand Up @@ -54,19 +54,27 @@ def column_aliases
@cfg['column-aliases']
end

def column_substitutes
@cfg['column-substitutes']
end

def logfields
@logfields ||=
Sql::ColumnList.new(self, @cfg['logrecord-fields-with-type'])
Sql::ColumnList.new(self,
@cfg['logrecord-fields-with-type'],
self.column_substitutes)
end

def milefields
@milefields ||=
Sql::ColumnList.new(self, @cfg['milestone-fields-with-type'])
Sql::ColumnList.new(self, @cfg['milestone-fields-with-type'],
self.column_substitutes)
end

def fakefields
@fakefields ||=
Sql::ColumnList.new(self, @cfg['fake-fields-with-type'])
Sql::ColumnList.new(self, @cfg['fake-fields-with-type'],
self.column_substitutes)
end

def [](name)
Expand Down
3 changes: 2 additions & 1 deletion src/sql/crawl_query.rb
Expand Up @@ -5,6 +5,7 @@
require 'sql/field_predicate'
require 'sql/column_resolver'
require 'sql/field_resolver'
require 'sql/aggregate_expression'

module Sql
class CrawlQuery
Expand Down Expand Up @@ -261,7 +262,7 @@ def summary_fields
raise "Extra fields (#{@extra_fields.extra}) contain non-aggregates"
end
extras = @extra_fields.fields.map { |f|
f.to_sql
Sql::AggregateExpression.aggregate_sql(@summary_tables, f)
}.join(", ")
end
[basefields, extras].find_all { |x| x && !x.empty? }.join(", ")
Expand Down
6 changes: 6 additions & 0 deletions src/sql/field.rb
Expand Up @@ -134,6 +134,12 @@ def reference_field
self.resolve(self.sql_column_name + '_id')
end

def bind_ordered_column!
if self.column && self.column.ordered_column_alias
self.name = self.column.ordered_column_alias
end
end

def === (name)
if name.is_a?(Enumerable)
name.any? { |n| @name == n }
Expand Down
4 changes: 4 additions & 0 deletions src/sql/field_predicates.rb
Expand Up @@ -12,6 +12,10 @@ def type
field.type
end

def bind_ordered_column!
self.field.bind_ordered_column!
end

def resolve(new_field_name)
clone = self.dup
clone.field = self.field.resolve(new_field_name)
Expand Down
2 changes: 1 addition & 1 deletion src/sql/lookup_table_config.rb
Expand Up @@ -47,7 +47,7 @@ def find_fields
def find_generated_columns
return [] if !@lookup_cfg || @lookup_cfg.is_a?(Array)
generated_fields = @lookup_cfg['generated-fields'] || []
generated_fields.map { |f| Sql::Column.new(@cfg, f) }
generated_fields.map { |f| Sql::Column.new(@cfg, f, {}) }
end
end
end
2 changes: 1 addition & 1 deletion src/sql/lookup_table_registry.rb
Expand Up @@ -44,7 +44,7 @@ def lookup_matches?(lookup, column)

return lookup['generated-fields'] &&
lookup['generated-fields'].map { |f|
Sql::Column.new(@cfg, f)
Sql::Column.new(@cfg, f, {})
}.find { |c| c.name == column.name }
end
end
Expand Down
3 changes: 2 additions & 1 deletion src/sql/query_table.rb
Expand Up @@ -22,7 +22,8 @@ def dup
def column_list
@column_list ||=
Sql::ColumnList.new(SQL_CONFIG,
SQL_CONFIG["#{@name}-fields-with-type"])
SQL_CONFIG["#{@name}-fields-with-type"],
SQL_CONFIG.column_substitutes)
end

def generated_columns
Expand Down
4 changes: 3 additions & 1 deletion src/sqlhelper.rb
Expand Up @@ -30,6 +30,7 @@
require 'query/summary_graph_builder'
require 'crawl/branch_set'
require 'crawl/gods'
require 'string_fixup'

include Tourney
include HenzellConfig
Expand All @@ -43,7 +44,8 @@

include Query::Grammar

BRANCHES = Crawl::BranchSet.new(CFG['branches'])
PLACE_FIXUPS = StringFixup.new(CFG['place-fixups'])
BRANCHES = Crawl::BranchSet.new(CFG['branches'], PLACE_FIXUPS)
UNIQUES = Set.new(CFG['uniques'].map { |u| u.downcase })
GODS = Crawl::Gods.new(CFG['god'])

Expand Down
22 changes: 22 additions & 0 deletions src/string_fixup.rb
@@ -0,0 +1,22 @@
class StringFixup
def initialize(fixup_map)
@map = Hash[fixup_map.map { |key, value|
value = [value] unless value.is_a?(Array)
value = value.map { |r|
r.sub(%r/\$(\d)/, '\\\1')
}
[%r/#{key}/i, value]
}]
end

def fixup(text)
for regex, replacements in @map
if text =~ regex
return replacements.map { |r|
text.sub(regex, r)
}
end
end
[text]
end
end
5 changes: 5 additions & 0 deletions tests/testcmd.txt
Expand Up @@ -213,3 +213,8 @@ E !lg * s=trunc99(sc)
!lg * fe--
!lg * --fe
!lg * __he

!lg * v:1
!lg * s=src x=max(cv),max(v),min(cv),min(v)
!lg * x=max(trunc500(turn))
!lg * max=cv

0 comments on commit f025e65

Please sign in to comment.