Commit 0dbec5ef authored by Simon Will's avatar Simon Will
Browse files

Implement meters and verse positions

parent a1aae0f7
Loading
Loading
Loading
Loading
+16 −8
Original line number Diff line number Diff line
@@ -3,19 +3,27 @@

import re

from .model import Reading
from .model import Reading, Position


def caesurae_together(positions, reward):
def caesurae_together(position_specs, reward):
    def get_reward(meter: Meter, reading: Reading):
        # TODO: Check if caesurae occur.
        for spec in position_specs:
            position = Position.after(spec[0], reading, meter, spec[1])
            if not position.word_boundary:
                return 0
        else:
            return reward
    return get_reward


def bridge(position, reward):
    def get_reward(meter: Meter, reading: Reading):
        # TODO: Check if bridge occurs.
        position = Position.after(position_spec[0], reading, meter,
                                  position_spec[1])
        if position.word_boundary:
            return 0
        else:
            return reward
    return get_reward

@@ -32,7 +40,7 @@ class Meter:
        self.short_name = short_name

    def match_reading(self, reading: Reading):
        return re.match(self.schema, reading.get_syllable_schema())
        return re.match(self.schema, reading.get_schema())

    def get_rewards(self, reading: Reading):
        return sum(cond(reading) for cond in self.conditions)
@@ -45,7 +53,7 @@ ALL_METERS = [
        conditions={
            caesurae_together([('mora', 6, 'Trithemimeral'),
                               ('mora', 14, 'Hephthemimeral')], 2),
            caesurae_together([('mora', 10, 'Penthemimeral')], 1),
            caesurae_together([('mora', 10, 'Penthemimeral')], 2),
            caesurae_together([('mora', 16, 'Bucolic Diaeresis')], 1),
            bridge(('mora', 15, 'Hermann’s Bridge'), 1)
        },
+60 −1
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ def minimal(full_dict:dict):
    #print(result_dict)
    return result_dict


class Syllable:

    def __init__(self, syllable: str, span: List[int], idx: int,
@@ -345,6 +346,17 @@ class Reading:

        return reading

    def get_schema(self):
        schema_list = []
        for token in self.tokens:
            for syllable in token.syllables:
                if syllable.syllable_length == 1:
                    schema_list.append('')
                elif syllable.syllable_length == 2:
                    schema_list.append('')
                # If length == 0, don’t append a symbol.
        return ''.join(schema_list)

    def to_dict(self):

        features = dict()
@@ -356,7 +368,6 @@ class Reading:

        return minimal(features)


    def to_json(self):

        return json.dumps(self.to_dict())
@@ -431,3 +442,51 @@ class Verse:
        readings_str = '\n'.join(str(r) for r in self.readings)
        return s.format(verse=self.text, reading_num=len(self.readings),
                        readings=readings_str)


class Position:

    def __init__(self, reading: Reading, mora: int, word_boundary: bool,
                 token: Token, syllable: Syllable,
                 meter: '.meters.Meter' = None, element: int = None):
        self.reading = reading
        self.mora = mora
        self.word_boundary = word_boundary
        self.meter = meter
        self.element = element

    @classmethod
    def after_mora(cls, reading: Reading, mora: int) -> 'Position':
        morae = 0
        position = None
        for token in reading.tokens:
            for i, syllable in enumerate(token.syllables):
                word_boundary = i == 0
                if morae == mora:
                    position = cls(
                        reading=reading, mora=mora, token=token,
                        syllable=syllable, word_boundary=word_boundary,
                        meter=meter
                    )
                else:
                    morae += syllable.syllable_length
        return position

    @classmethod
    def after_element(cls, reading: Reading, meter: '.meters.Meter',
                      element: int) -> 'Position':
        # TODO: Implement this.
        pass

    @classmethod
    def after(cls, type: str, reading: Reading, position_number: int,
             meter: '.meters.Meter') -> 'Position':
        if type == 'mora':
            return cls.after_mora(*args, reading, position_number)
        elif type == 'element':
            return cls.after_element(*args, reading, meter, position_number)
        else:
            raise ValueError(
                'The after type has to be "mora" or "element", but is {!r}'
                .format(spec)
            )