Map: Compare precision against 4 not 0 [#792]

staging
gnosygnu 4 years ago
parent 72051f4ce9
commit 316c6c6a58

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
Copyright (C) 2012-2020 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
@ -13,12 +13,16 @@ The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.xowa.xtns.mapSources; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import org.junit.*;
public class Map_dd2dms_func_tst {
@Before public void init() {fxt.Reset();} private final Xop_fxt fxt = new Xop_fxt();
@Test public void Example() {fxt.Test_parse_tmpl_str_test("{{#dd2dms: 14.58|precision=4}}" , "{{test}}" , "14° 34' 48"");}
@Test public void Plus() {fxt.Test_parse_tmpl_str_test("{{#dd2dms: 14.58|precision=4|plus=pos}}" , "{{test}}" , "14° 34' 48" pos");}
@Test public void Ws() {fxt.Test_parse_tmpl_str_test("{{#dd2dms: 14.58| precision = 4 | plus = pos }}" , "{{test}}" , "14° 34' 48" pos");}
@Test public void Nested_pfunc() {fxt.Test_parse_tmpl_str_test("{{#dd2dms: 14.58|{{#if:2|precision=2}}}}" , "{{test|3}}" , "14° 34'");} // handle "{{#if:2|precision=2}}" -> "precision=2"
}
package gplx.xowa.xtns.mapSources;
import gplx.xowa.Xop_fxt;
import org.junit.Before;
import org.junit.Test;
public class Map_dd2dms_func_tst {
@Before public void init() {fxt.Reset();} private final Xop_fxt fxt = new Xop_fxt();
@Test public void Example() {fxt.Test_parse_tmpl_str_test("{{#dd2dms: 14.58|precision=4}}" , "{{test}}" , "14° 34' 48"");}
@Test public void Plus() {fxt.Test_parse_tmpl_str_test("{{#dd2dms: 14.58|precision=4|plus=pos}}" , "{{test}}" , "14° 34' 48" pos");}
@Test public void Ws() {fxt.Test_parse_tmpl_str_test("{{#dd2dms: 14.58| precision = 4 | plus = pos }}" , "{{test}}" , "14° 34' 48" pos");}
@Test public void Nested_pfunc() {fxt.Test_parse_tmpl_str_test("{{#dd2dms: 14.58|{{#if:2|precision=2}}}}" , "{{test|3}}" , "14° 35'");} // handle "{{#if:2|precision=2}}" -> "precision=2"
}

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
Copyright (C) 2012-2020 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
@ -13,293 +13,306 @@ The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.xowa.xtns.mapSources; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
import gplx.core.primitives.*; import gplx.core.btries.*;
import gplx.xowa.parsers.*; import gplx.xowa.parsers.tmpls.*;
class Map_math {// REF.MW:MapSources_math.php
private int word_idx_nsew;
private double[] rv = new double[4];
private byte dir_id;
private int prec;
private int step;
public double Dec() {return dec;} private double dec;
public int Error() {return error;} private int error;
public double Coord_dec() {return coord_dec;} private double coord_dec;
public double Coord_deg() {return coord_deg;} private double coord_deg;
public double Coord_min() {return coord_min;} private double coord_min;
public double Coord_sec() {return coord_sec;} private double coord_sec;
public byte[] Coord_dir_ns() {return coord_dir_ns;} private byte[] coord_dir_ns;
public byte[] Coord_dir_ew() {return coord_dir_ew;} private byte[] coord_dir_ew;
public boolean Ctor(byte[] input, int prec, byte[] dir, int until_step) {
try {
New_coord(input, dir, prec);
if (until_step > 1 && error == 0)
Set_coord();
} catch (Exception e) {
Err_.Noop(e);
error = -128;
}
return error == 0;
}
public void Fail(Xop_ctx ctx, byte[] src, Xot_invk self, Bry_bfr bfr, byte[] pfunc_name) {
String page_str = ctx.Page().Url().To_str();
String pfunc_name_str = String_.new_u8(pfunc_name);
String self_str = String_.new_u8(src, self.Src_bgn(), self.Src_end());
switch (error) {
case -1: // empty coord; EX: {{#deg2dd:|precision=6}}}} PAGE:it.v:Sami; DATE:2014-03-02
case -2: // words > 4; EX:{{#geoLink: $1 $2 $3 $4 $5 $6|lat=51°2000″19°5550″}}; PAGE:pl.v:Rezerwat_przyrody_Jaksonek DATE:2014-08-14
case -3: // invalid delim; EX:{{#geoLink: $1 $2 $3 $4 $5 $6|lat=51°3137″|long=20°1317'}}; PAGE:pl.v:Rezerwat_przyrody_Ciosny DATE:2014-08-14
ctx.App().Usr_dlg().Log_many("", "", "mapSources failed: page=~{0} pfunc=~{1} err=~{2} src=~{3}", page_str, pfunc_name_str, error, self_str); // don't warn b/c there are many
break;
default:
ctx.App().Usr_dlg().Warn_many("", "", "mapSources failed: page=~{0} pfunc=~{1} err=~{2} src=~{3}", page_str, pfunc_name_str, error, self_str);
break;
}
}
private void New_coord(byte[] input, byte[] dir, int prec) { // REF.MW:newCoord
this.error = 0; this.word_idx_nsew = -1;
coord_dec = coord_deg = coord_min = coord_sec = 0;
rv[0] = rv[1] = rv[2] = 0; rv[3] = 1;
this.dir_id = Parse_dir(dir);
this.prec = Parse_precision(prec);
this.dec = 0;
this.step = 0;
Parse_input(input);
}
private void Set_coord() { // REF.MW:setCoord
if (step > 1) return;
if (prec < 9)
dec = Math_.Round(dec, prec);
int sign = dec < 0 ? -1 : 1;
double angle = Math_.Abs_double(dec);
double deg = Math_.Floor(angle);
double min = (angle - deg) * 60;
double sec = prec > 0
? Math_.Round((min - Math_.Floor(min)) * 60, prec - 4)
: Math_.Round((min - Math_.Floor(min)) * 60, 0)
;
min = Math_.Floor(min);
if (sec >= 60) {
sec -= 60;
min++;
}
if (prec < 3 && sec >= 30)
min++;
if (prec < 3)
sec = 0;
if (min >= 60) {
min -= 60;
deg++;
}
if (prec < 1 && min >= 30) {
deg++;
}
if (prec < 1)
min = 0;
coord_dec = Math_.Round(dec, prec);
coord_deg = deg * sign;
coord_min = min;
coord_sec = sec;
if (sign > 0) {
coord_dir_ns = Compass_N;
coord_dir_ew = Compass_E;
}
else {
coord_dir_ns = Compass_S;
coord_dir_ew = Compass_W;
}
step = 2;
}
public byte[] Get_dms(boolean wikibase, byte[] plus, byte[] minus) { // REF.MW: getDMSString
if (step < 2) Set_coord();
double deg = coord_deg;
if ( dec < 0
&& ( (Bry_.Len_gt_0(plus) || Bry_.Len_gt_0(minus))
|| wikibase // NOTE: wikibase will always pass in empty plus / minus; still need to suppress "-" sign because letter has already been reversed; EX:"-2 E" -> "2 W" x> "-2 W" DATE:2017-04-02
)
) {
deg = Math_.Abs_double(deg);
}
tmp_bfr.Add_double(deg).Add(Bry_deg);
if (prec > 0) {
if (!wikibase) // NOTE: do not add space if wikibase, else will fail in Module:en.w:WikidataCoord; PAGE:en.w:Hulme_Arch_Bridge DATE:2017-04-02
tmp_bfr.Add_byte_space();
tmp_bfr.Add_double(coord_min).Add(wikibase ? Bry_apos_wb : Bry_apos_mw);
}
if (prec > 2) {
if (!wikibase) // NOTE: do not add space if wikibase, else will fail in Module:en.w:WikidataCoord; PAGE:en.w:Hulme_Arch_Bridge DATE:2017-04-02
tmp_bfr.Add_byte_space();
tmp_bfr.Add_double(coord_sec).Add(wikibase ? Bry_quot_wb : Bry_quot_mw);
}
byte[] letter = null;
if (dir_id == Dir_lat_id)
letter = coord_dir_ns;
if (dir_id == Dir_long_id)
letter = coord_dir_ew;
if (dec > 0 && Bry_.Len_gt_0(plus))
letter = plus;
if (dec < 0 && Bry_.Len_gt_0(minus))
letter = minus;
if (letter != null) {
tmp_bfr.Add_byte_space();
tmp_bfr.Add(letter);
}
return tmp_bfr.To_bry_and_clear();
}
private void Parse_input(byte[] src) { // REF.MW: toDec
src = Parse_input_normalize(tmp_bfr, src);
if (src == null) {error = -1; return;}
int src_len = src.length;
int word_idx = -1, word_bgn = 0, words_len = 0;
int i = 0;
while (true) {
boolean is_last = i == src_len;
byte b = is_last ? Byte_ascii.Space : src[i];
switch (b) {
case Byte_ascii.Space:
Parse_input_word(rv, src, ++word_idx, word_bgn, i);
++words_len;
i = Bry_find_.Find_fwd_while_space_or_tab(src, i, src_len);
word_bgn = i;
break;
}
if (is_last) break;
i++;
}
if (words_len < 1 || words_len > 4) {error = -2; return;}
if (word_idx_nsew != -1 && word_idx_nsew != words_len - 1) {error = -10; return;}
if (rv[0] >= 0)
dec = (rv[0] + rv[1] / 60 + rv[2] / 3600 ) * rv[3];
else
dec = (rv[0] - rv[1] / 60 - rv[2] / 3600 ) * rv[3];
this.step = 1;
}
private boolean Parse_input_word_is_compass(byte v) {
switch (v) {
case Byte_ascii.Ltr_N:
case Byte_ascii.Ltr_E:
case Byte_ascii.Ltr_S:
case Byte_ascii.Ltr_W:
return true;
default:
return false;
}
}
private void Parse_input_word(double[] rv, byte[] input, int word_idx, int word_bgn, int word_end) {
if (word_idx >= Input_units_len) return;
byte unit_dlm = Input_units[word_idx];
int pos = Bry_find_.Find_fwd(input, unit_dlm, word_bgn, word_end);
if (pos != Bry_find_.Not_found) // remove dlms from end of bry; EX: "123'" -> "123"
word_end = pos;
if (!Parse_input_word_is_compass(input[word_bgn])) { // if ( is_numeric( $v ) ) {
double word_val = Bry_.To_double_or(input, word_bgn, word_end, Double_.NaN);
if (!Double_.IsNaN(word_val)) {
if (word_idx > 2) {error = -4; return;}
switch (word_idx) {
case 0:
if (word_val <= -180 || word_val > 180) {error = -5; return;}
rv[0] = word_val;
break;
case 1:
if (word_val < 0 || word_val >= 60) {error = -6; return;}
if (rv[0] != (int)(rv[0])) {error = -7; return;}
rv[1] = word_val;
break;
case 2:
if (word_val < 0 || word_val >= 60) {error = -8; return;}
if (rv[1] != (int)(rv[1])) {error = -9; return;}
rv[2] = word_val;
break;
}
}
else {
error = -3;
return;
}
}
else { // 'NSEW'
word_idx_nsew = word_idx;
byte word_byte = input[word_bgn];
if (rv[0] < 0) {error = -11; return;}
if (word_end - word_bgn != 1) {error = -3; return;}
switch (dir_id) {
case Dir_long_id:
if (word_byte == Byte_ascii.Ltr_N || word_byte == Byte_ascii.Ltr_S) {error = -12; return;}
break;
case Dir_lat_id:
if (word_byte == Byte_ascii.Ltr_E || word_byte == Byte_ascii.Ltr_W) {error = -12; return;}
break;
case Dir_unknown_id:
if (word_byte == Byte_ascii.Ltr_N || word_byte == Byte_ascii.Ltr_S) this.dir_id = Dir_lat_id;
else this.dir_id = Dir_long_id;
break;
}
if (this.dir_id == Dir_lat_id) {
double rv_0 = rv[0];
if (rv_0 < -90 || rv_0 > 90) {error = -13; return;}
}
if (word_byte == Byte_ascii.Ltr_S || word_byte == Byte_ascii.Ltr_W)
rv[3] = -1;
}
}
private static byte Parse_dir(byte[] dir) {
if (Bry_.Len_eq_0(dir)) return Dir_unknown_id;
Object dir_obj = Dir_trie.Match_bgn(dir, 0, dir.length);
return dir_obj == null ? Dir_unknown_id : ((Byte_obj_val)dir_obj).Val();
}
private static int Parse_precision(int val) { // REF.MW: MapSourcesMath.php|newCoord
if (val > -1 && val < 10) return val;
else if (val == -1) return 9;
else return 4;
}
private Bry_bfr tmp_bfr = Bry_bfr_.Reset(32);
public static byte[] Parse_input_normalize(Bry_bfr bfr, byte[] src) {
/*
$w = str_replace( array( '', '', '' ), "'", $input );
$w = str_replace( array( "''", '“', '”', '″' ), '"', $w );
$w = str_replace( '', '-', $w );
$w = strtoupper( str_replace( array( '_', '/', "\t", "\n", "\r" ), ' ', $w ) );
$w = str_replace( array( '°', "'", '"' ), array( '° ', "' ", '" ' ), $w );
$w = trim( str_replace( array( 'N', 'S', 'E', 'W' ), array( ' N', ' S', ' E', ' W' ), $w ) );
*/
int src_end = src.length; if (src_end == 0) return null;
src = Trie__normalize__apos.Replace(bfr, src, 0, src_end); // normalize apos separately, since 2 apos can go to quotes; EX: -> "; PAGE:it.v:Morro_d'Oro DATE:2015-12-06
src = Trie__normalize__rest.Replace(bfr, src, 0, src.length); // normalize rest;
return Bry_.Trim(src);
}
private static final byte[]
Bry_deg = Bry_.new_u8("°")
, Bry_quot_mw = Bry_.new_a7("&quot;")
, Bry_quot_wb = Bry_.new_a7("&#34;") // REF:en.w:Module:WikidataCoord
, Bry_apos_mw = Bry_.new_a7("'")
, Bry_apos_wb = Bry_.new_a7("&#39;") // REF:en.w:Module:WikidataCoord
;
private static final byte Dir_unknown_id = 0, Dir_lat_id = 1, Dir_long_id = 2;
public static final byte[] Dir_lat_bry = Bry_.new_a7("lat"), Dir_long_bry = Bry_.new_a7("long");
private static final Btrie_slim_mgr Dir_trie = Btrie_slim_mgr.ci_a7() // NOTE:ci.ascii:MW_const.en
.Add_bry_byte(Dir_lat_bry , Dir_lat_id)
.Add_bry_byte(Dir_long_bry , Dir_long_id)
;
private static final byte[]
Compass_N = new byte[] {Byte_ascii.Ltr_N}
, Compass_E = new byte[] {Byte_ascii.Ltr_E}
, Compass_S = new byte[] {Byte_ascii.Ltr_S}
, Compass_W = new byte[] {Byte_ascii.Ltr_W}
;
private static final byte Input_byte_degree = Byte_ascii.Slash; // NOTE: ugly cheat to avoid using multi-byte char; note that all "/" are swapped out to " ", so any remaining "/" was added by the normalizer; EX: "123° 4/5" -> "123/ 4 5"
private static final byte[] Input_units = new byte[] {Input_byte_degree, Byte_ascii.Apos, Byte_ascii.Quote, Byte_ascii.Space};
private static final int Input_units_len = Input_units.length;
private static final Btrie_slim_mgr Trie__normalize__apos = Btrie_slim_mgr.cs()
.Add_replace_many (Byte_ascii.Apos_bry , "", "", "");
private static final Btrie_slim_mgr Trie__normalize__rest = Btrie_slim_mgr.cs()
.Add_replace_many ("' " , "'")
.Add_replace_many ("\" " , "\"", "''", "“", "”", "″")
.Add_replace_many (Byte_ascii.Dash_bry , "-", "") // NOTE: emdash and endash
.Add_replace_many (Byte_ascii.Space_bry , " ", "_", "/", "\t", "\n", "\r") // NOTE: " " = &nbsp;
.Add_replace_many ("/ " , "°")
.Add_replace_many (" N" , "N", "n")
.Add_replace_many (" S" , "S", "s")
.Add_replace_many (" E" , "E", "e")
.Add_replace_many (" W" , "W", "w");
public static final Map_math Instance = new Map_math();
}
package gplx.xowa.xtns.mapSources;
import gplx.Bry_;
import gplx.Bry_bfr;
import gplx.Bry_bfr_;
import gplx.Bry_find_;
import gplx.Byte_ascii;
import gplx.Double_;
import gplx.Err_;
import gplx.Math_;
import gplx.String_;
import gplx.core.btries.Btrie_slim_mgr;
import gplx.core.primitives.Byte_obj_val;
import gplx.xowa.parsers.Xop_ctx;
import gplx.xowa.parsers.tmpls.Xot_invk;
class Map_math {// REF.MW:MapSources_math.php
private int word_idx_nsew;
private double[] rv = new double[4];
private byte dir_id;
private int prec;
private int step;
public double Dec() {return dec;} private double dec;
public int Error() {return error;} private int error;
public double Coord_dec() {return coord_dec;} private double coord_dec;
public double Coord_deg() {return coord_deg;} private double coord_deg;
public double Coord_min() {return coord_min;} private double coord_min;
public double Coord_sec() {return coord_sec;} private double coord_sec;
public byte[] Coord_dir_ns() {return coord_dir_ns;} private byte[] coord_dir_ns;
public byte[] Coord_dir_ew() {return coord_dir_ew;} private byte[] coord_dir_ew;
public boolean Ctor(byte[] input, int prec, byte[] dir, int until_step) {
try {
New_coord(input, dir, prec);
if (until_step > 1 && error == 0)
Set_coord();
} catch (Exception e) {
Err_.Noop(e);
error = -128;
}
return error == 0;
}
public void Fail(Xop_ctx ctx, byte[] src, Xot_invk self, Bry_bfr bfr, byte[] pfunc_name) {
String page_str = ctx.Page().Url().To_str();
String pfunc_name_str = String_.new_u8(pfunc_name);
String self_str = String_.new_u8(src, self.Src_bgn(), self.Src_end());
switch (error) {
case -1: // empty coord; EX: {{#deg2dd:|precision=6}}}} PAGE:it.v:Sami; DATE:2014-03-02
case -2: // words > 4; EX:{{#geoLink: $1 $2 $3 $4 $5 $6|lat=51°2000″19°5550″}}; PAGE:pl.v:Rezerwat_przyrody_Jaksonek DATE:2014-08-14
case -3: // invalid delim; EX:{{#geoLink: $1 $2 $3 $4 $5 $6|lat=51°3137″|long=20°1317'}}; PAGE:pl.v:Rezerwat_przyrody_Ciosny DATE:2014-08-14
ctx.App().Usr_dlg().Log_many("", "", "mapSources failed: page=~{0} pfunc=~{1} err=~{2} src=~{3}", page_str, pfunc_name_str, error, self_str); // don't warn b/c there are many
break;
default:
ctx.App().Usr_dlg().Warn_many("", "", "mapSources failed: page=~{0} pfunc=~{1} err=~{2} src=~{3}", page_str, pfunc_name_str, error, self_str);
break;
}
}
private void New_coord(byte[] input, byte[] dir, int prec) { // REF.MW:newCoord
this.error = 0; this.word_idx_nsew = -1;
coord_dec = coord_deg = coord_min = coord_sec = 0;
rv[0] = rv[1] = rv[2] = 0; rv[3] = 1;
this.dir_id = Parse_dir(dir);
this.prec = Parse_precision(prec);
this.dec = 0;
this.step = 0;
Parse_input(input);
}
private void Set_coord() { // REF.MW:setCoord
if (step > 1) return;
if (prec < 9)
dec = Math_.Round(dec, prec);
int sign = dec < 0 ? -1 : 1;
double angle = Math_.Abs_double(dec);
double deg = Math_.Floor(angle);
double min = (angle - deg) * 60;
double sec = prec > 4 // 2020-09-03|ISSUE#:792|precision check should be > 4 not > 0;PAGE:en.w:Huntington_Plaza
? Math_.Round((min - Math_.Floor(min)) * 60, prec - 4)
: Math_.Round((min - Math_.Floor(min)) * 60, 0)
;
min = Math_.Floor(min);
if (sec >= 60) {
sec -= 60;
min++;
}
if (prec < 3 && sec >= 30)
min++;
if (prec < 3)
sec = 0;
if (min >= 60) {
min -= 60;
deg++;
}
if (prec < 1 && min >= 30) {
deg++;
}
if (prec < 1)
min = 0;
coord_dec = Math_.Round(dec, prec);
coord_deg = deg * sign;
coord_min = min;
coord_sec = sec;
if (sign > 0) {
coord_dir_ns = Compass_N;
coord_dir_ew = Compass_E;
}
else {
coord_dir_ns = Compass_S;
coord_dir_ew = Compass_W;
}
step = 2;
}
public byte[] Get_dms(boolean wikibase, byte[] plus, byte[] minus) { // REF.MW: getDMSString
if (step < 2) Set_coord();
double deg = coord_deg;
if ( dec < 0
&& ( (Bry_.Len_gt_0(plus) || Bry_.Len_gt_0(minus))
|| wikibase // NOTE: wikibase will always pass in empty plus / minus; still need to suppress "-" sign because letter has already been reversed; EX:"-2 E" -> "2 W" x> "-2 W" DATE:2017-04-02
)
) {
deg = Math_.Abs_double(deg);
}
tmp_bfr.Add_double(deg).Add(Bry_deg);
if (prec > 0) {
if (!wikibase) // NOTE: do not add space if wikibase, else will fail in Module:en.w:WikidataCoord; PAGE:en.w:Hulme_Arch_Bridge DATE:2017-04-02
tmp_bfr.Add_byte_space();
tmp_bfr.Add_double(coord_min).Add(wikibase ? Bry_apos_wb : Bry_apos_mw);
}
if (prec > 2) {
if (!wikibase) // NOTE: do not add space if wikibase, else will fail in Module:en.w:WikidataCoord; PAGE:en.w:Hulme_Arch_Bridge DATE:2017-04-02
tmp_bfr.Add_byte_space();
tmp_bfr.Add_double(coord_sec).Add(wikibase ? Bry_quot_wb : Bry_quot_mw);
}
byte[] letter = null;
if (dir_id == Dir_lat_id)
letter = coord_dir_ns;
if (dir_id == Dir_long_id)
letter = coord_dir_ew;
if (dec > 0 && Bry_.Len_gt_0(plus))
letter = plus;
if (dec < 0 && Bry_.Len_gt_0(minus))
letter = minus;
if (letter != null) {
tmp_bfr.Add_byte_space();
tmp_bfr.Add(letter);
}
return tmp_bfr.To_bry_and_clear();
}
private void Parse_input(byte[] src) { // REF.MW: toDec
src = Parse_input_normalize(tmp_bfr, src);
if (src == null) {error = -1; return;}
int src_len = src.length;
int word_idx = -1, word_bgn = 0, words_len = 0;
int i = 0;
while (true) {
boolean is_last = i == src_len;
byte b = is_last ? Byte_ascii.Space : src[i];
switch (b) {
case Byte_ascii.Space:
Parse_input_word(rv, src, ++word_idx, word_bgn, i);
++words_len;
i = Bry_find_.Find_fwd_while_space_or_tab(src, i, src_len);
word_bgn = i;
break;
}
if (is_last) break;
i++;
}
if (words_len < 1 || words_len > 4) {error = -2; return;}
if (word_idx_nsew != -1 && word_idx_nsew != words_len - 1) {error = -10; return;}
if (rv[0] >= 0)
dec = (rv[0] + rv[1] / 60 + rv[2] / 3600 ) * rv[3];
else
dec = (rv[0] - rv[1] / 60 - rv[2] / 3600 ) * rv[3];
this.step = 1;
}
private boolean Parse_input_word_is_compass(byte v) {
switch (v) {
case Byte_ascii.Ltr_N:
case Byte_ascii.Ltr_E:
case Byte_ascii.Ltr_S:
case Byte_ascii.Ltr_W:
return true;
default:
return false;
}
}
private void Parse_input_word(double[] rv, byte[] input, int word_idx, int word_bgn, int word_end) {
if (word_idx >= Input_units_len) return;
byte unit_dlm = Input_units[word_idx];
int pos = Bry_find_.Find_fwd(input, unit_dlm, word_bgn, word_end);
if (pos != Bry_find_.Not_found) // remove dlms from end of bry; EX: "123'" -> "123"
word_end = pos;
if (!Parse_input_word_is_compass(input[word_bgn])) { // if ( is_numeric( $v ) ) {
double word_val = Bry_.To_double_or(input, word_bgn, word_end, Double_.NaN);
if (!Double_.IsNaN(word_val)) {
if (word_idx > 2) {error = -4; return;}
switch (word_idx) {
case 0:
if (word_val <= -180 || word_val > 180) {error = -5; return;}
rv[0] = word_val;
break;
case 1:
if (word_val < 0 || word_val >= 60) {error = -6; return;}
if (rv[0] != (int)(rv[0])) {error = -7; return;}
rv[1] = word_val;
break;
case 2:
if (word_val < 0 || word_val >= 60) {error = -8; return;}
if (rv[1] != (int)(rv[1])) {error = -9; return;}
rv[2] = word_val;
break;
}
}
else {
error = -3;
return;
}
}
else { // 'NSEW'
word_idx_nsew = word_idx;
byte word_byte = input[word_bgn];
if (rv[0] < 0) {error = -11; return;}
if (word_end - word_bgn != 1) {error = -3; return;}
switch (dir_id) {
case Dir_long_id:
if (word_byte == Byte_ascii.Ltr_N || word_byte == Byte_ascii.Ltr_S) {error = -12; return;}
break;
case Dir_lat_id:
if (word_byte == Byte_ascii.Ltr_E || word_byte == Byte_ascii.Ltr_W) {error = -12; return;}
break;
case Dir_unknown_id:
if (word_byte == Byte_ascii.Ltr_N || word_byte == Byte_ascii.Ltr_S) this.dir_id = Dir_lat_id;
else this.dir_id = Dir_long_id;
break;
}
if (this.dir_id == Dir_lat_id) {
double rv_0 = rv[0];
if (rv_0 < -90 || rv_0 > 90) {error = -13; return;}
}
if (word_byte == Byte_ascii.Ltr_S || word_byte == Byte_ascii.Ltr_W)
rv[3] = -1;
}
}
private static byte Parse_dir(byte[] dir) {
if (Bry_.Len_eq_0(dir)) return Dir_unknown_id;
Object dir_obj = Dir_trie.Match_bgn(dir, 0, dir.length);
return dir_obj == null ? Dir_unknown_id : ((Byte_obj_val)dir_obj).Val();
}
private static int Parse_precision(int val) { // REF.MW: MapSourcesMath.php|newCoord
if (val > -1 && val < 10) return val;
else if (val == -1) return 9;
else return 4;
}
private Bry_bfr tmp_bfr = Bry_bfr_.Reset(32);
public static byte[] Parse_input_normalize(Bry_bfr bfr, byte[] src) {
/*
$w = str_replace( array( '', '', '' ), "'", $input );
$w = str_replace( array( "''", '“', '”', '″' ), '"', $w );
$w = str_replace( '', '-', $w );
$w = strtoupper( str_replace( array( '_', '/', "\t", "\n", "\r" ), ' ', $w ) );
$w = str_replace( array( '°', "'", '"' ), array( '° ', "' ", '" ' ), $w );
$w = trim( str_replace( array( 'N', 'S', 'E', 'W' ), array( ' N', ' S', ' E', ' W' ), $w ) );
*/
int src_end = src.length; if (src_end == 0) return null;
src = Trie__normalize__apos.Replace(bfr, src, 0, src_end); // normalize apos separately, since 2 apos can go to quotes; EX: -> "; PAGE:it.v:Morro_d'Oro DATE:2015-12-06
src = Trie__normalize__rest.Replace(bfr, src, 0, src.length); // normalize rest;
return Bry_.Trim(src);
}
private static final byte[]
Bry_deg = Bry_.new_u8("°")
, Bry_quot_mw = Bry_.new_a7("&quot;")
, Bry_quot_wb = Bry_.new_a7("&#34;") // REF:en.w:Module:WikidataCoord
, Bry_apos_mw = Bry_.new_a7("'")
, Bry_apos_wb = Bry_.new_a7("&#39;") // REF:en.w:Module:WikidataCoord
;
private static final byte Dir_unknown_id = 0, Dir_lat_id = 1, Dir_long_id = 2;
public static final byte[] Dir_lat_bry = Bry_.new_a7("lat"), Dir_long_bry = Bry_.new_a7("long");
private static final Btrie_slim_mgr Dir_trie = Btrie_slim_mgr.ci_a7() // NOTE:ci.ascii:MW_const.en
.Add_bry_byte(Dir_lat_bry , Dir_lat_id)
.Add_bry_byte(Dir_long_bry , Dir_long_id)
;
private static final byte[]
Compass_N = new byte[] {Byte_ascii.Ltr_N}
, Compass_E = new byte[] {Byte_ascii.Ltr_E}
, Compass_S = new byte[] {Byte_ascii.Ltr_S}
, Compass_W = new byte[] {Byte_ascii.Ltr_W}
;
private static final byte Input_byte_degree = Byte_ascii.Slash; // NOTE: ugly cheat to avoid using multi-byte char; note that all "/" are swapped out to " ", so any remaining "/" was added by the normalizer; EX: "123° 4/5" -> "123/ 4 5"
private static final byte[] Input_units = new byte[] {Input_byte_degree, Byte_ascii.Apos, Byte_ascii.Quote, Byte_ascii.Space};
private static final int Input_units_len = Input_units.length;
private static final Btrie_slim_mgr Trie__normalize__apos = Btrie_slim_mgr.cs()
.Add_replace_many (Byte_ascii.Apos_bry , "", "", "");
private static final Btrie_slim_mgr Trie__normalize__rest = Btrie_slim_mgr.cs()
.Add_replace_many ("' " , "'")
.Add_replace_many ("\" " , "\"", "''", "“", "”", "″")
.Add_replace_many (Byte_ascii.Dash_bry , "-", "") // NOTE: emdash and endash
.Add_replace_many (Byte_ascii.Space_bry , " ", "_", "/", "\t", "\n", "\r") // NOTE: " " = &nbsp;
.Add_replace_many ("/ " , "°")
.Add_replace_many (" N" , "N", "n")
.Add_replace_many (" S" , "S", "s")
.Add_replace_many (" E" , "E", "e")
.Add_replace_many (" W" , "W", "w");
public static final Map_math Instance = new Map_math();
}

@ -1,6 +1,6 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
Copyright (C) 2012-2020 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
@ -13,202 +13,207 @@ The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
package gplx.xowa.xtns.wbases.pfuncs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.wbases.*;
import org.junit.*; import gplx.xowa.parsers.*; import gplx.xowa.parsers.tmpls.*;
public class Wdata_pf_property__basic__tst {
@Before public void init() {fxt.Init();} private final Wdata_wiki_mgr_fxt fxt = new Wdata_wiki_mgr_fxt();
@Test public void String() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_string(1, "a"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "a");
fxt.Test_parse("{{#property:p2}}", "");
}
@Test public void Entity() {
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_label("en", "b")
);
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_entity_qid(1, 2))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "b");
}
@Test public void Entity_fr() { // PURPOSE: non-English wiki should default to English label if non-English label not available; DATE:2013-12-19
// set wiki to French
fxt.Wiki().Wdata_wiki_lang_(Bry_.new_a7("fr"));
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_entity_qid(1, 2))
.Add_sitelink("frwiki", "Test_page")
);
// create wdata page Q2 with label in en (not fr)
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_label("en", "b")
);
// parse; should get en label
fxt.Test_parse("{{#property:p1}}", "b");
}
@Test public void Entity_missing() { // PURPOSE: wiki may refer to entity that no longer exists; EX: {{#property:p1}} which links to Q1, but p1 links to Q2 and Q2 was deleted; DATE:2014-02-01
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_entity_qid(1, 2)) // create wdata page Q1 with prop entity reference to Q2; note that Q2 is not created
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", ""); // parse; get ""
}
@Test public void Time() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_time(1, "2012-01-02 03:04:05"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "30405 2 Jan 2012"); // NOTE: format is missing ":" b/c test does not init messages for html_wtr; DATE:2015-08-03
}
@Test public void Geodata() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_geo(1, "6.789", "1.2345"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "1°14&#39;4.2&#34;N, 6°47&#39;20.4&#34;E");
}
@Test public void Quantity__plus_minus__y() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_quantity(1, "+1234", "1", "+1236", "+1232"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "1,234±2");
}
@Test public void Quantity__plus_minus__n() { // PURPOSE:do not output ± if lbound == val == ubound; PAGE:en.w:Tintinan DATE:2015-08-02
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_quantity(1, "+1234", "1", "+1234", "+1234"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "1,234");
}
@Test public void Quantity__range() { // PURPOSE:do not output ± if lbound == val == ubound; PAGE:en.w:Tintinan DATE:2015-08-02
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_quantity(1, "+1234", "1", "+1236", "+1233"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "1,233-1,236");
}
@Test public void Quantity__long() { // PURPOSE: must cast to long for large numbers; EX:{{#property:P1082}} PAGE:en.w:Earth; DATE:2015-08-02
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_quantity(1, "+4321000000", "1", "4321000000", "4321000000"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "4,321,000,000");
}
@Test public void Quantity__unit__entity() {// PURPOSE: get entity name; EX:{{#invoke:Wikidata|getUnits|P2386|FETCH_WIKIDATA}} PAGE:en.w:Arecibo_Observatory; DATE:2016-10-11
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_quantity(1, "+1234", "http://www.wikidata.org/entity/Q2", "+1236", "+1232"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_claims(fxt.Make_claim_string(2, "a"))
.Add_label("en", "meter")
);
fxt.Test_parse("{{#property:p1}}", "1,234±2 meter");
}
@Test public void Quantity__decimal() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_quantity(1, "+1234.50", "1", "+1236.75", "+1232.25"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "1,234.5±2.25");
}
@Test public void Monolingualtext() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_monolingual(1, "la", "Lorem ipsum dolor sit amet"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "Lorem ipsum dolor sit amet");
}
@Test public void Novalue() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_novalue(1))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "no value");
}
@Test public void Somevalue() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_somevalue(1))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "unknown value");
}
@Test public void Multiple() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_string(1, "a"), fxt.Make_claim_string(1, "b"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "a"); // only take first; DATE:2015-08-02
}
@Test public void Q() {
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_claims(fxt.Make_claim_string(1, "a"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1|q=Q2}}", "a");
}
@Test public void Of() {
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_claims(fxt.Make_claim_string(1, "a"))
.Add_sitelink("enwiki", "Of_page")
);
fxt.Test_parse("{{#property:p1|of=Of_page}}", "a");
}
@Test public void From() {
fxt.Init__docs__add(fxt.Wdoc("Property:P2")
.Add_claims(fxt.Make_claim_string(1, "a"))
);
fxt.Test_parse("{{#property:p1|from=P2}}", "a");
fxt.Test_parse("{{#property:p1|from=}}", "");
fxt.Test_parse("{{#property:p1| from = P2 }}", "a"); // PURPOSE: trim ws; ISSUE#:361; DATE:2019-02-11
}
@Test public void Pid_as_name() {
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_claims(fxt.Make_claim_string(1, "a"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Init_pids_add("en", "astronomic symbol", 1);
fxt.Test_parse("{{#property:astronomic symbol}}", "a");
}
@Test public void Empty_arg() { // PURPOSE: {{#property:p1|}} should not fail / warn; DATE:2013-11-15
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_claims(fxt.Make_claim_string(1, "a"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Init_pids_add("en", "astronomic symbol", 1);
fxt.Test_parse("{{#property:p1|}}", "a");
}
@Test public void Parse_pid() {
fxt.Test_parse_pid ("p123" , 123); // basic
fxt.Test_parse_pid ("P123" , 123); // uppercase
fxt.Test_parse_pid_null ("population"); // name test
fxt.Test_parse_pid_null ("123"); // missing p
fxt.Test_parse_pid_null (""); // empty String test
}
}
package gplx.xowa.xtns.wbases.pfuncs;
import gplx.Bry_;
import gplx.xowa.xtns.wbases.Wdata_wiki_mgr_fxt;
import org.junit.Before;
import org.junit.Test;
public class Wdata_pf_property__basic__tst {
@Before public void init() {fxt.Init();} private final Wdata_wiki_mgr_fxt fxt = new Wdata_wiki_mgr_fxt();
@Test public void String() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_string(1, "a"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "a");
fxt.Test_parse("{{#property:p2}}", "");
}
@Test public void Entity() {
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_label("en", "b")
);
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_entity_qid(1, 2))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "b");
}
@Test public void Entity_fr() { // PURPOSE: non-English wiki should default to English label if non-English label not available; DATE:2013-12-19
// set wiki to French
fxt.Wiki().Wdata_wiki_lang_(Bry_.new_a7("fr"));
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_entity_qid(1, 2))
.Add_sitelink("frwiki", "Test_page")
);
// create wdata page Q2 with label in en (not fr)
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_label("en", "b")
);
// parse; should get en label
fxt.Test_parse("{{#property:p1}}", "b");
}
@Test public void Entity_missing() { // PURPOSE: wiki may refer to entity that no longer exists; EX: {{#property:p1}} which links to Q1, but p1 links to Q2 and Q2 was deleted; DATE:2014-02-01
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_entity_qid(1, 2)) // create wdata page Q1 with prop entity reference to Q2; note that Q2 is not created
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", ""); // parse; get ""
}
@Test public void Time() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_time(1, "2012-01-02 03:04:05"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "30405 2 Jan 2012"); // NOTE: format is missing ":" b/c test does not init messages for html_wtr; DATE:2015-08-03
}
@Test public void Geodata() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_geo(1, "6.789", "1.2345"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "1°14&#39;4.2&#34;N, 6°47&#39;20.4&#34;E");
}
@Test public void Quantity__plus_minus__y() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_quantity(1, "+1234", "1", "+1236", "+1232"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "1,234±2");
}
@Test public void Quantity__plus_minus__n() { // PURPOSE:do not output ± if lbound == val == ubound; PAGE:en.w:Tintinan DATE:2015-08-02
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_quantity(1, "+1234", "1", "+1234", "+1234"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "1,234");
}
@Test public void Quantity__range() { // PURPOSE:do not output ± if lbound == val == ubound; PAGE:en.w:Tintinan DATE:2015-08-02
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_quantity(1, "+1234", "1", "+1236", "+1233"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "1,233-1,236");
}
@Test public void Quantity__long() { // PURPOSE: must cast to long for large numbers; EX:{{#property:P1082}} PAGE:en.w:Earth; DATE:2015-08-02
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_quantity(1, "+4321000000", "1", "4321000000", "4321000000"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "4,321,000,000");
}
@Test public void Quantity__unit__entity() {// PURPOSE: get entity name; EX:{{#invoke:Wikidata|getUnits|P2386|FETCH_WIKIDATA}} PAGE:en.w:Arecibo_Observatory; DATE:2016-10-11
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_quantity(1, "+1234", "http://www.wikidata.org/entity/Q2", "+1236", "+1232"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_claims(fxt.Make_claim_string(2, "a"))
.Add_label("en", "meter")
);
fxt.Test_parse("{{#property:p1}}", "1,234±2 meter");
}
@Test public void Quantity__decimal() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_quantity(1, "+1234.50", "1", "+1236.75", "+1232.25"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "1,234.5±2.25");
}
@Test public void Monolingualtext() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_monolingual(1, "la", "Lorem ipsum dolor sit amet"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "Lorem ipsum dolor sit amet");
}
@Test public void Novalue() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_novalue(1))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "no value");
}
@Test public void Somevalue() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_somevalue(1))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "unknown value");
}
@Test public void Multiple() {
fxt.Init__docs__add(fxt.Wdoc("Q1")
.Add_claims(fxt.Make_claim_string(1, "a"), fxt.Make_claim_string(1, "b"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1}}", "a"); // only take first; DATE:2015-08-02
}
@Test public void Q() {
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_claims(fxt.Make_claim_string(1, "a"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Test_parse("{{#property:p1|q=Q2}}", "a");
}
@Test public void Of() {
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_claims(fxt.Make_claim_string(1, "a"))
.Add_sitelink("enwiki", "Of_page")
);
fxt.Test_parse("{{#property:p1|of=Of_page}}", "a");
}
@Test public void From() {
fxt.Init__docs__add(fxt.Wdoc("Property:P2")
.Add_claims(fxt.Make_claim_string(1, "a"))
);
fxt.Test_parse("{{#property:p1|from=P2}}", "a");
fxt.Test_parse("{{#property:p1|from=}}", "");
fxt.Test_parse("{{#property:p1| from = P2 }}", "a"); // PURPOSE: trim ws; ISSUE#:361; DATE:2019-02-11
}
@Test public void Pid_as_name() {
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_claims(fxt.Make_claim_string(1, "a"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Init_pids_add("en", "astronomic symbol", 1);
fxt.Test_parse("{{#property:astronomic symbol}}", "a");
}
@Test public void Empty_arg() { // PURPOSE: {{#property:p1|}} should not fail / warn; DATE:2013-11-15
fxt.Init__docs__add(fxt.Wdoc("Q2")
.Add_claims(fxt.Make_claim_string(1, "a"))
.Add_sitelink("enwiki", "Test_page")
);
fxt.Init_pids_add("en", "astronomic symbol", 1);
fxt.Test_parse("{{#property:p1|}}", "a");
}
@Test public void Parse_pid() {
fxt.Test_parse_pid ("p123" , 123); // basic
fxt.Test_parse_pid ("P123" , 123); // uppercase
fxt.Test_parse_pid_null ("population"); // name test
fxt.Test_parse_pid_null ("123"); // missing p
fxt.Test_parse_pid_null (""); // empty String test
}
}

Loading…
Cancel
Save