 #
 # This file is part of the Anotatornia suite.
 # 
 # Copyright © 2007, 2008, 2009, 2010 by Instytut Podstaw Informatyki
 # Polskiej Akademii Nauk (IPI PAN; Institute of Computer Science, Polish
 # Academy of Sciences; cf. www.ipipan.waw.pl).  All rights reserved.
 # 
 # This file may be distributed and/or modified under the terms of the
 # GNU General Public License version 3 as published by the Free Software
 # Foundation and appearing in the file COPYING included in the packaging
 # of this file.  (See http://www.gnu.org/licenses/translations.html for
 # unofficial translations.)
 # 
 # A commercial license is available from IPI PAN (contact
 # Michal.Ciesiolka.waw.pl or ipi.waw.pl for more
 # information).  Licensees holding a valid commercial license from IPI
 # PAN may use this file in accordance with that license.
 # 
 # This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
 # THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 # PURPOSE.
 #

# == Schema Information
# Schema version: 10
#
# Table name: fraza_anot
#
#  fraza_anot_id     :integer         primary key
#  akapit_transzy_id :integer         not null
#  token_id_pocz     :integer         
#  token_id_kon      :integer         
#  token_id_synhead  :integer         
#  token_id_semhead  :integer         
#  fraza_typ_id      :integer         
#  vp_typ            :integer         
#  sie_typ           :integer         
#  created_at        :timestamp       
#  updated_at        :timestamp       
#

require 'ramkowanie'


class FrazaAnot < ActiveRecord::Base

raise "zunikalnij zmienne |tok| !"

  belongs_to :akapit_transzy
  belongs_to :fraza_typ

  belongs_to :token_pocz,
  :class_name => "Token" ,
  :foreign_key => "token_id_pocz"

  belongs_to :token_kon,
  :class_name => "Token" ,
  :foreign_key => "token_id_kon"

  belongs_to :token_semhead,
  :class_name => "Token" ,
  :foreign_key => "token_id_semhead"

  belongs_to :token_synhead,
  :class_name => "Token" ,
  :foreign_key => "token_id_synhead"


  TYP_SIE = [
             ['morfol.',      0],
             ['zwrotne',    1],
             ['wzajem.',   2],
             ['bezosob.',  3]
            ]

  include Ramkowanie # definiuje  stałe regexp CASES i string UNDEF

  
  def self.sie_zakres
    unless defined?(@@sie_zakres)
      @@sie_zakres = 0..(FrazaAnot::TYP_SIE.size - 1)
    end
    @@sie_zakres
  end #  of self.sie_zakres

  def dlugosc
    self.token_id_kon - self.token_id_pocz + 1
  end

  def tokens
    Token.find(
               :all,
               :conditions => {
               :token_id => (self.token_id_pocz)..(self.token_id_kon)},
               :order => :token_id)
  end


  def xheads(xhead_sym, param, ftypid=nil)
    ftypid = self.fraza_typ_id  unless ftypid # w warunku, bo wołamy tę metodę w miejscu,
    # gdy typ frazy dopiero ma zostać przypisany i podajemy go w parametrze.
    ftyp = FrazaTyp.find(ftypid) 
    self.tokens.collect{ |tok|
      ftyp.dopuszcza_glowe?( xhead_sym, tok, param )
    }.compact.sort
    # dostaniemy tablicę tablic [ -1/0, token], którą możemy posortować, bo Token ma metodę <=>
  end # of xheads



  def synheads(param, ftypid=nil)
    self.xheads(:synh, param, ftypid)
  end


  def semheads(param, ftypid=nil)
    self.xheads(:semh, param, ftypid)
  end

  if DlaEli.x
    def finitywna?
      if self.fraza_typ_id == FrazaTyp.find_id( 'VP' ) : return true
      else return false
      end
    end # of finitywna? dla Eli
  else
    def finitywna?
      return false
    end# of finitywna? dla AP
  end

  def get_uzid
    # od 2008/09/01 prawdopodobnie niepotrzebna, w każdym razie nie używana w tym pliku.
    self.akapit_transzy.get_uzid
  end

  def akat_hash
    { :akapit_transzy_id => self.akapit_transzy_id }
  end


  def reszta_tagu( headsym, param=nil )
    param ||= self.akat_hash
    tsh = self.send( headsym )
    # domyślnie bierzemy głowę semantyczną, jeśli jej nie ma, bierzemy syntakt.
    tsh ||= self.token_synhead
    if tsh : tsh.disambs( param )[0].reszta_tagu
    else 
      ''
    end
  end # of reszta_tagu

  def przypadek( headsym, param=nil )
    # symbol głowy zawsze trzeba podać, bo dla prepnp będzie to semhead, a dla np — synhead
    param ||= self.akat_hash
    rt = self.reszta_tagu( headsym, param )
    rt =~ CASES
    return $1.to_s
  end # of przypadek

  def sem_lemat( param=nil )
    param ||= self.akat_hash
    tsh =  self.token_semhead
    if tsh : tsh.disambs( param )[0].leksem.lemat    
    else ''
    end
  end # of sem_lemat


  def syn_lemat( param=nil )
    param ||= self.akat_hash
    tsh =  self.token_synhead
    if tsh : tsh.disambs( param )[0].leksem.lemat    
    else ''
    end
  end # of syn_lemat

  def tag( full=false, param=nil )
    #<zabierać :np:nom: :prepnp:do:gen: :prepnp:w:loc: :sie:>
    # 0-8 zabierać aff:fin:sg:_:pri:: cpos cpor
    #	[0-3:fw:prepnp:w:cisza:loc:: st,
    #    3-5:sie,
    #	5-8:fw:prepnp:do:czytanie:gen:: czy]
    # do używania przy „zrzucie na spłaszczoną świgrę”
    # full idzie tylko w zrzucie na spłaszczoną Świgrę.

    # ustawiony dla typów fraz EH. Czy będzie potrzebna dla NKJP?
    
    param ||= self.akat_hash
    
    sft=self.fraza_typ 
    if sft :    typ = sft.typ_symbol.downcase
    else      typ=nil
    end
    
    if full :   tag0="#{typ}"
      # na początku było „fw:”, ale Ela go nie chce w zrzucie na spłaszczoną Świgrę.
    else tag0="#{typ}"
    end
    
    semh = self.sem_lemat( param )
    semh ='none' if semh ==''

    case typ
      
    when 'adjp' # frazę przymiotnikową uznajemy za realizację wymagania rzeczownikowego
      if full : tag0 = tag0 +':'+  semh + self.reszta_tagu( :token_synhead,  param )
      else   tag0= 'adjp:' + self.przypadek( :token_synhead, param )
      end
      
    when 'advp'
      tag0 += ":#{semh}"      if full
      # z jakiegoś powodu we wzorcu są advp bez stopnia przysłówka (bez reszty tagu)
      
    when 'np'
      if full 
        tag0 = tag0 + ':' + semh +  self.reszta_tagu( :token_synhead,  param )
        tag0 += ':ter' unless tag0 =~ /(pri|sec|ter)$/
      else tag0 = tag0 +':' + self.przypadek( :token_synhead, param )
      end
      
    when 'nump' # zakładam, że fraza liczebnikowa realizuje walencję rzeczownikową
      if full : tag0 = tag0 + ':' + self.sem_lemat( param ) + self.reszta_tagu( :token_synhead, param )
        # czy w braku głowy semantycznej (rzeczownika) lemat ma zostać pusty, czy dać liczebnik?
        # czy może „NONE”?
      else   tag0='np:' + self.przypadek( :token_synhead, param )
      end
      
    when 'prepadjp' 
      # we frazach prepadjp, prepnp i prepnump ignorujemy liczbę i rodzaj, dla zgodności z formatem MW/AP, czyli zastępujemy »reszta_tagu« przez »:+przypadek«.
      if full : tag0 = tag0 + ':' +self.syn_lemat( param ) +':'+ semh + ':' + 
          self.przypadek( :token_semhead, param )
      else tag0 = 'prepadjp:' + self.syn_lemat( param )
        przyp = self.przypadek(  :token_semhead, param )
        tag0  += ':' + przyp if przyp.jlength > 0 
      end
      
    when 'prepnp'
      if full : tag0 = tag0 +':'+ self.syn_lemat( param ) +':'+ semh + ':' + 
          self.przypadek( :token_semhead,  param )
      else tag0 = tag0 +':'+ self.syn_lemat( param )+':' + 
          self.przypadek(  :token_semhead, param )
      end
      
    when 'prepnump' # realizuje walencję prepnp
      if full : tag0 = tag0 +':'+ self.syn_lemat( param ) +':'+ semh + ':' +
          self.przypadek( :token_semhead,  param )
      else tag0 = 'prepnp:' + self.syn_lemat( param ) +':'+
          self.przypadek( :token_semhead, param )
      end
      
    when 'sie' # Ela chce wyróżniać »się« bezosobowe jako frazę luźną.
      if full
        if self.sie_typ == 3 : tag0 = 'np:sie:sg:nom:n:ter:: pron' 
          # »się« bezosobowe zastępuje mianownik.
          # sens zwróci  '' i nie zostanie dopisany w exsemaval.
        else tag0 = 'sie'
        end
      else # nie full
        tag0 = 'np:nom' if self.sie_typ == 3 
      end
      # w przypadku nie-full  całym tagiem »się« nie-bezosobowego jet typ ( „sie”)
      
    when 'vp'
      if self.vp_typ == 0
        tag0 = "neg:fin"
      else tag0 = "aff:fin"
      end
      tag0 = tag0 + self.reszta_tagu( :token_synhead,  param ) 
      
    else
      if typ==nil :   tag0=':???'
      else      raise "nie rozpoznany typ frazy: #{typ}"
      end
    end # of #{case}.
    
    ##    tag0+= ':' unless full
    return tag0
  end # of #{tag}.
  
  
  def sens( param=nil, pole=:sens_opis )
    # do używania przy „zrzucie na spłaszczoną świgrę”
    # param dajemy jako arg. opcjonalny, żeby można go było policzyć raz na zewnątrz i przekazać.
    param ||= self.akat_hash
    s = self.token_semhead
    s =  s.sens( param ) if s
    if s : return s.sensy.send( pole ) # 2008/07/18 Ela chce pełnym słowem
      # pełnym słowem w Anotatorni, oznaczeniem w zrzucie na spłaszczoną Świgrę
    elsif  self.fraza_typ_id == FrazaTyp.find_id( 'sie' ) : return ''
      # co z sensem nump i prepnump, jeśli nie ma rzeczownika? -  ma być UNDEF 
      # nump ---> np itd, ale nie w liście fraz, prawda?
    else return UNDEF
    end
  end# of #{sens}.


end # of class


### Local Variables: 
### mode: ruby
### End:
