Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Auto measure label handling #302

Open
wants to merge 61 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
46b9420
auto join measure labels if point to same zone
riedde Dec 24, 2022
293159d
fix measure label join with multirests
riedde Dec 24, 2022
b962381
add diacrtical aspects to measure labels
riedde Dec 27, 2022
58f67ce
add css for deleted measures
riedde Dec 27, 2022
461e631
introduce module for measure actions
riedde Dec 27, 2022
271543c
fix default return type
riedde Dec 27, 2022
47d5278
add functx namespace
riedde Mar 13, 2023
e59e582
introduce handling for reg
riedde Mar 13, 2023
3911b17
Merge branch 'develop' into ftr/measure-label-handling
riedde Feb 7, 2024
1a4d91d
measure: move local functions to module
riedde Feb 7, 2024
74d16bc
Merge branch 'develop' into ftr/measure-label-handling
bwbohl Feb 25, 2024
9b068a7
add and format structuring comments, XQdoc comments
bwbohl Feb 26, 2024
119d928
apply current XQuery style guide
bwbohl Feb 26, 2024
d7da75b
fix return tpe to proper JSON
bwbohl Feb 26, 2024
2ec2790
Merge branch 'develop' into ftr/measure-label-handling
riedde Jun 21, 2024
14837c2
adding else case if no multiple measures point to a zone
riedde Jun 21, 2024
43d8b28
Merge branch 'develop' into ftr/measure-label-handling
riedde Sep 18, 2024
59e2af5
Merge branch 'develop' into ftr/measure-label-handling
riedde Nov 6, 2024
7e614ff
Merge branch 'develop' into ftr/measure-label-handling
riedde Nov 7, 2024
09974a5
add first test for the measure module
peterstadler Nov 8, 2024
9b2d51e
fixing broken syntax
riedde Nov 7, 2024
62cc4d4
adding documentation and return types #302
riedde Nov 13, 2024
e9fa11f
Merge branch 'develop' into ftr/measure-label-handling
riedde Nov 13, 2024
2beae37
extend handling for mei:perfRes attributes
riedde Nov 13, 2024
da9a7ec
need to catch errors and failures
peterstadler Nov 15, 2024
ce0b55a
add initial test for `measure:resolveMultiMeasureRests#2`
peterstadler Nov 15, 2024
ae98754
Update add/data/xqm/measure.xqm
riedde Nov 23, 2024
f0dc4b6
Update add/data/xqm/measure.xqm
riedde Nov 23, 2024
c3971d7
Update add/data/xqm/measure.xqm
riedde Nov 23, 2024
006fe7b
Update add/data/xqm/measure.xqm
riedde Nov 23, 2024
537bf5e
Update add/data/xqm/measure.xqm
riedde Dec 4, 2024
7f89d50
small adjustments following suggestions of the code review
riedde Dec 4, 2024
d81ae8a
Merge branch 'ftr/measure-label-handling' of github.com:Edirom/Edirom…
riedde Dec 4, 2024
b1bcda6
Update add/data/xqm/measure.xqm
riedde Dec 10, 2024
5915413
Update add/data/xqm/measure.xqm
riedde Dec 10, 2024
c8ec168
revert 7f89d50c0325b1fc77daf65c20407236eef61ed9 partially
riedde Dec 10, 2024
a7a604f
adding xhtml namespace to created elements
riedde Dec 10, 2024
5522f8a
update variable names, remove obsolete loop
riedde Dec 10, 2024
b2456dc
Merge branch 'develop' into ftr/measure-label-handling
riedde Dec 10, 2024
8708dcc
fix syntax error
riedde Dec 10, 2024
741a51a
add fallback (key not found)
riedde Dec 10, 2024
13c8c8b
fix namespace and module location
riedde Dec 10, 2024
e5dc953
add extended handling for perfRes labeling
riedde Dec 10, 2024
5452ba6
Update add/data/xqm/measure.xqm
riedde Dec 10, 2024
6946585
Update add/data/xqm/measure.xqm
riedde Dec 10, 2024
2acb3b2
Update add/data/xqm/measure.xqm
riedde Dec 10, 2024
91349fa
Update add/data/xqm/measure.xqm
riedde Dec 10, 2024
07141a9
Update add/data/xqm/measure.xqm
riedde Dec 10, 2024
def111d
Update testing/XQSuite/measure-tests.xqm
riedde Dec 10, 2024
77ddd9c
Update add/data/xqm/measure.xqm
riedde Dec 10, 2024
88212eb
Update add/data/xqm/measure.xqm
riedde Dec 10, 2024
4d745b9
add test for `getMeasureLabel#1`
peterstadler Dec 11, 2024
89b86cd
remove import for unused module
riedde Dec 16, 2024
2ad0a2d
remove brackets and comment
riedde Dec 16, 2024
4eefd32
changed strings-maps to json-maps
riedde Dec 16, 2024
01568d2
return array instead of maps* #302
riedde Dec 17, 2024
45082e6
refactor `measure:analyzeLabel#1`
peterstadler Dec 17, 2024
d72d013
properly return a JSON array
peterstadler Dec 17, 2024
decd562
comment out not-working and not needed code
peterstadler Dec 18, 2024
c9ed32f
comment out test for disabled function
peterstadler Dec 18, 2024
b45c7b5
Merge branch 'develop' into ftr/measure-label-handling
peterstadler Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 6 additions & 96 deletions add/data/xql/getMeasures.xql
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import module namespace functx = "http://www.functx.com";

import module namespace eutil = "http://www.edirom.de/xquery/util" at "/db/apps/Edirom-Online/data/xqm/util.xqm";

import module namespace measure = "http://www.edirom.de/xquery/measure" at "/db/apps/Edirom-Online/data/xqm/measure.xqm";
riedde marked this conversation as resolved.
Show resolved Hide resolved

(: NAMESPACE DECLARATIONS ================================================== :)

declare namespace mei = "http://www.music-encoding.org/ns/mei";
Expand All @@ -20,107 +22,15 @@ declare namespace xmldb = "http://exist-db.org/xquery/xmldb";

declare option exist:serialize "method=text media-type=text/plain omit-xml-declaration=yes";

(: FUNCTION DECLARATIONS =================================================== :)

declare function local:getMeasures($mei as node(), $mdivID as xs:string) as xs:string* {

if ($mei//mei:parts) then (
let $mdiv := $mei/id($mdivID)
let $measureNs :=
if ($mdiv//mei:measure/@label) then (
let $labels := $mdiv//mei:measure/@label/string()
for $label in $labels
let $labelsAnalyzed :=
if (contains($label, '–')) then (
(:substring-before($label, '–'):)
let $first := substring-before($label, '–')
let $last := substring-after($label, '–')
let $steps := xs:integer(number($last) - number($first) + number(1))
for $i in 1 to $steps
return
string(number($first) + $i - 1)
) else
($label)
return
$labelsAnalyzed
) else
($mdiv//mei:measure/@n)

let $measureNsDistinct := distinct-values(eutil:sort-as-numeric-alpha($measureNs))

return
for $measureN in $measureNsDistinct
let $measureNNumber := number($measureN)
let $measures :=
if ($mdiv//mei:measure/@label) then
($mdiv//mei:measure[.//mei:multiRest][number(substring-before(@label, '–')) <= $measureNNumber][.//mei:multiRest/number(@num) gt ($measureNNumber - number(substring-before(@label, '–')))])
else
($mdiv//mei:measure[.//mei:multiRest][number(@n) lt $measureNNumber][.//mei:multiRest/number(@num) gt ($measureNNumber - number(@n))])
let $measures :=
for $part in $mdiv//mei:part
let $partMeasures :=
if ($part//mei:measure/@label) then
($part//mei:measure[@label = $measureN][1])
else
($part//mei:measure[@n = $measureN][1])
for $measure in $partMeasures | $measures[ancestor::mei:part = $part]
let $voiceRef := $part//mei:staffDef/@decls
return
concat(
'{id:"', $measure/@xml:id, '",
voice: "', $voiceRef,
'", partLabel: "', eutil:getPartLabel($measure, 'measure'),
'"}'
)
return
concat(
'{',
'id: "measure_', $mdiv/@xml:id, '_', $measureN, '", ',
'measures: [', string-join($measures, ','), '], ',
'mdivs: ["', $mdiv/@xml:id, '"], ', (: TODO :)
'name: "', $measureN, '"',
'}'
)
) else (
if ($mei/id($mdivID)//mei:measure[@label]) then (
for $measureN in $mei/id($mdivID)//mei:measure/@label
let $measures := $mei/id($mdivID)//mei:measure[@label = $measureN]
let $measure := $measures[1]
(:let $measureLabel := if(exists($measure/@label) and not(contains($measure/@label,'/'))) then($measure/@label) else($measure/@n):)
return
concat(
'{',
'id: "', $measure/@xml:id, '", ',
'measures: [{id:"', $measure/@xml:id, '", voice: "score"}], ',
'mdivs: ["', $measure/ancestor::mei:mdiv[1]/@xml:id, '"], ', (: TODO :)
'name: "', $measureN, '"', (: Hier Unterscheiden wg. Auftakt. :)
'}'
)
) else (
for $measureN in $mei/id($mdivID)//mei:measure/data(@n)
let $measures := $mei/id($mdivID)//mei:measure[@n = $measureN]
let $measure := $measures[1]
(:let $measureLabel := if(exists($measure/@label) and not(contains($measure/@label,'/'))) then($measure/@label) else($measure/@n):)
return
concat(
'{',
'id: "', $measure/@xml:id, '", ',
'measures: [{id:"', $measure/@xml:id, '", voice: "score"}], ',
'mdivs: ["', $measure/ancestor::mei:mdiv[1]/@xml:id, '"], ', (: TODO :)
'name: "', $measureN, '"', (: Hier Unterscheiden wg. Auftakt. :)
'}'
)
)
)
};

(: QUERY BODY ============================================================== :)

let $uri := request:get-parameter('uri', '')
let $mdivID := request:get-parameter('mdiv', '')
let $mei := doc($uri)/root()

let $ret := local:getMeasures($mei, $mdivID)
let $ret := measure:getMeasures($mei, $mdivID)

return
concat('[', string-join($ret, ','), ']')

'[' || string-join($ret, ',') || ']'

66 changes: 8 additions & 58 deletions add/data/xql/getMeasuresOnPage.xql
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ xquery version "3.1";
@author <a href="mailto:[email protected]">Daniel Röwenstrunk</a>
:)

(: IMPORTS ================================================================= :)

import module namespace eutil="http://www.edirom.de/xquery/util" at "/db/apps/Edirom-Online/data/xqm/util.xqm";

import module namespace measure = "http://www.edirom.de/xquery/measure" at "/db/apps/Edirom-Online/data/xqm/measure.xqm";

(: NAMESPACE DECLARATIONS ================================================== :)

declare namespace mei = "http://www.music-encoding.org/ns/mei";
Expand All @@ -22,60 +28,6 @@ declare namespace xmldb = "http://exist-db.org/xquery/xmldb";
declare option output:method "json";
declare option output:media-type "application/json";

(: FUNCTION DECLARATIONS =================================================== :)

(:~
Finds all measures on a page.

@param $mei The sourcefile
@param $surface The surface to look at
@returns A list of json objects with measure information
:)
declare function local:getMeasures($mei as node(), $surface as node()) as map(*)* {

for $zone in $surface/mei:zone[@type = 'measure']
let $zoneRef := concat('#', $zone/@xml:id)
(:
The first predicate with `contains` is just a rough estimate to narrow down the result set.
It uses the index and is fast while the second (exact) predicate is generally too slow
:)
let $measures := $mei//mei:measure[contains(@facs, $zoneRef)][$zoneRef = tokenize(@facs, '\s+')]
return
for $measure in $measures
let $measureLabel :=
if ($measure/@label) then
($measure/string(@label))
else
($measure/string(@n))
let $measureLabel :=
if ($measure//mei:multiRest) then
($measureLabel || '–' || number($measureLabel) + number($measure//mei:multiRest/@num) - 1)
else
($measureLabel)
return
map {
'zoneId': $zone/string(@xml:id),
'ulx': $zone/string(@ulx),
'uly': $zone/string(@uly),
'lrx': $zone/string(@lrx),
'lry': $zone/string(@lry),
'id': $measure/string(@xml:id),
'name': $measureLabel,
'type': $measure/string(@type),
'rest': local:getMRest($measure)
}
};

declare function local:getMRest($measure) {

if ($measure//mei:mRest) then
(string('1'))
else if ($measure//mei:multiRest) then
($measure//mei:multiRest/string(@num))
else
(string('0'))
};

(: QUERY BODY ============================================================== :)

let $uri := request:get-parameter('uri', '')
Expand All @@ -85,8 +37,6 @@ let $mei := doc($uri)/root()
let $surface := $mei/id($surfaceId)

return (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please keep the array constructor (or force measure:getMeasuresOnPage#2 to return an array)

Copy link
Contributor Author

@riedde riedde Dec 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At 2ad0a2d
The round brackets are removed. The function returns a map. Why should there be an array?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

measure:getMeasures#2 returns a sequence of maps. If the sequence is gt 1 this will automatically be serialized to a JSON array. If the sequence is 1 the return type will be a JSON object. If it's 0 the return type will be NULL.
This is quite annoying for the frontend so it's much nicer to always return an array.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@peterstadler Done at 01568d2 I don't have time today to work on this, so if necessary, please fix directly before tomorrow's release.

array {
(: TODO: überlegen, wie die Staff-spezifischen Ausschnitte angezeigt werden sollen :)
local:getMeasures($mei, $surface)
}
(: TODO: überlegen, wie die Staff-spezifischen Ausschnitte angezeigt werden sollen :)
measure:getMeasuresOnPage($mei, $surface)
)
Loading