Esempio n. 1
0
def jsrTemp(val, lang):
    if val == 0: return N("zero") if lang == "en" else N("zéro")
    if val < 0:
        return AdvP(A("minus") if lang == "en" else Adv("moins"), NO(abs(val)))
    if val <= 5:
        return AP(A("plus"), NO(val)) if lang == "en" else AdvP(
            Adv("plus"), NO(val))
    return NO(val)
Esempio n. 2
0
def makeSyntR(semR, checkSpecial=True):
    # checkSpecial is False when called from within specialConcept.checkSpecialConcept
    #              to avoid infinite loop
    traceSyntR("makeSyntR", semR)
    concept = semR.concept
    if concept == None:  # l'instance réfère à un autre AMR
        return instance2SyntR(semR)
    if checkSpecial:
        sConcept = specialConcept.checkSpecialConcept(semR)
        if sConcept != None:
            traceSyntR("special concept", concept)
            return sConcept
    # evaluate each role to build the environment
    dictInfo = getSyntR(concept)
    env = Env()
    opts = Options()
    roles = semR.get_roles()
    if isVerb(concept):  #only for verbs
        # HACK for passive :  seem to be too aggressive.... so we keep it only for top-level AMR
        # generate a passive sentence if concept has an :ARG0 and the actual roles does not have :ARG0 but has :ARG1
        # %% do not passivate the special case of bear-02 because it is already passive
        if concept!="bear-02" and semR.parent==None and \
           ":ARG0" in verbs[concept].args and ":ARG0" not in semR.roles and ":ARG1" in semR.roles:
            opts.add("typ", {"pas": True})

    roleProcessing.processRoles(concept, roles, [], dictInfo, env, opts)

    ## patch the syntactic structures for frequent special cases
    if isVerb(concept):
        # HACK for changing nominative pronoun to accusative for :ARG1 when :ARG0 is also present
        if ":ARG1" in env and ":ARG0" in env and isinstance(
                env[":ARG1"], Pro) and env[":ARG1"].lemma == "I":
            env[":ARG1"].lemma = "me"
    elif isAdjective(concept):  # adjective with :ARG0 and :ARG1
        adj = dictInfo.lemma
        if ":ARG0" in env and ":ARG1" in env:
            if isinstance(env[":ARG0"], Pro) and env[":ARG0"].lemma == "me":
                env[":ARG0"].lemma = "I"
            if isinstance(env[":ARG1"], Pro) and env[":ARG1"].lemma == "I":
                env[":ARG0"].lemma = "me"
            dictInfo = LexSem(
                adj, "S", [":ARG0", ":ARG1"], lambda arg0, arg1: S(
                    arg0, VP(V("be"), A(adj), pp("for", arg1))))
        elif ":ARG1" in env and ":ARG2" in env:
            if isinstance(env[":ARG1"], Pro) and env[":ARG1"].lemma == "me":
                env[":ARG1"].lemma = "I"
            if isinstance(env[":ARG2"], Pro) and env[":ARG2"].lemma == "I":
                env[":ARG2"].lemma = "me"
            dictInfo = LexSem(
                adj, "S", [":ARG1", ":ARG2"], lambda arg1, arg2: S(
                    arg1, VP(V("be"), A(adj), pp("for", arg2))))
        elif ":ARG1" in env:
            if isinstance(env[":ARG1"], Pro) and env[":ARG1"].lemma == "me":
                env[":ARG1"].lemma = "I"
            dictInfo = LexSem(adj, "S", [":ARG1"],
                              lambda arg1: S(arg1, VP(V("be"), A(adj))))
    syntR = dictInfo.apply(env, opts)
    return syntR
Esempio n. 3
0
def makeA(lemma):
    adj=adjectives[lemma]
    if isinstance(adj,LexSem):
        return adj
    if isinstance(adj,AP):
        return LexSem(lemma,"A",[":ARG1"],lambda arg1:copy.deepcopy(adj).add(arg1))
    if isinstance(adj,A):
        return LexSem(lemma,"A",[":ARG1"],lambda arg1:AP(copy.deepcopy(adj),arg1))
    if isinstance(adj,str):
        return LexSem(lemma,"A",[":ARG1"],lambda arg1:A(adj) if arg1==None else AP(A(adj),arg1))
    print("### strange adjective:"+str(adj))
    return adj
Esempio n. 4
0
def ageRole(semR, env, opts):
    traceSyntR("ageRole", semR)
    if semR.get_concept() == "amr-unknown":
        env.unshift(Q("how old"))
        opts.add("a", "?")
    else:
        env.push(makeSyntR(semR).lier())
        env.push(A("old"))
Esempio n. 5
0
def modal(concept,roles,env,opts):
    traceSyntR("modal",concept)
    (adj,arg,option,t)=modals[concept]
#     print("roles:"+str(roles))
    if arg not in roles:
        return A(adj)
    argSyntR=makeSyntR(roles[arg])
    opts.add("t",t)
    opts.add("typ",{"mod":option})
    return addRoles(concept,roles,[arg],LexSem("modal","S",[],lambda:argSyntR),env,opts)
Esempio n. 6
0
def conditionRole(semR, env, opts):
    traceSyntR("conditionRole", semR)
    concept = semR.get_concept()
    if concept == "as-long-as":
        roles = semR.get_roles()
        if ":op1" in roles:
            env.push(PP(P("as"), A("long"), P("as"), makeSyntR(roles[":op1"])))
            return
    if concept == "otherwise":
        env.push(SP(C("otherwise"), makeSyntR(semR)))
    else:
        env.push(SP(C("if"), makeSyntR(semR)))
Esempio n. 7
0
def governmentOrganization(concept,roles,env,opts):
    traceSyntR("governmentOrganization", concept)
    if ":*:ARG0" in roles:
        if roles[":*:ARG0"].get_concept()=="govern-01":
            starArg0Roles=roles[":*:ARG0"].roles
            if len(roles)==1:
                return addRoles(concept, starArg0Roles, [":ARG0"], nounInfo("government"), env, opts)
            elif  ":ARG1" in starArg0Roles:
                dictInfo=nounInfo("government")
                env.push(PP(P("of"),makeSyntR(starArg0Roles[":ARG1"])))
                return addRoles(concept, starArg0Roles,[":ARG0",":ARG1"], dictInfo, env, opts)
    dictInfo=nounInfo("organization")
    env.put(":A",A("governmental"))
    return addRoles(concept, roles, [":*:ARG0"], dictInfo, env, opts)
Esempio n. 8
0
 def processTime(concept, syntR):
     if concept == "amr-unknown":
         opts.add("typ", {"int": "whn"})
         env.push(syntR)
     elif syntR == A("former"):
         env.unshift(Adv("formerly"))
     elif syntR == Q("ex"):
         env.unshift(syntR)
     elif syntR == Q("about to"):
         env.push(Adv("about"))
         env.push(P("to"))
     elif isVerb(concept):
         env.push(SP(C("when"), syntR))
     elif isinstance(syntR, A):
         env.push(Adv(adverbFromAdjective(syntR.lemma)))
     else:
         env.push(syntR)
Esempio n. 9
0
def title_block(wInfo, lang):
    issueDate = wInfo.get_issue_date()
    noSecond = {"second": False}
    if lang == "en":
        s1 = S(
            NP(N("forecast").n("p")),
            VP(
                V("issue").t("pp"),
                PP(
                    P("by"), Q("jsRealB"),
                    DT(issueDate).dOpt(noSecond), P("for"),
                    CP(
                        C("and"), N("today"),
                        DT(issueDate + datetime.timedelta(days=1)).dOpt(
                            {"rtime": issueDate})))))
        s2 = S(
            NP(D("the"), D("next"),
               V("schedule").t("pp"),
               N("forecast").n("p")),
            VP(
                V("be").t("f"),
                V("issue").t("pp"),
                DT(wInfo.get_next_issue_date()).dOpt(noSecond)))
    else:
        s1 = S(
            NP(N("prévision").n("p")),
            VP(
                V("émettre").t("pp"),
                PP(
                    P("par"), Q("jsRealB"),
                    DT(issueDate).dOpt(noSecond), P("pour"),
                    CP(
                        C("et"), Adv("aujourd'hui"),
                        DT(issueDate + datetime.timedelta(days=1)).dOpt(
                            {"rtime": issueDate})))))
        s2 = S(
            NP(D("le"),
               A("prochain").pos("pre"),
               N("prévision").n("p")),
            VP(
                V("être").t("f"),
                V("émettre").t("pp"),
                DT(wInfo.get_next_issue_date()).dOpt(noSecond)))
    return "\n".join([realize(s1, lang, False), realize(s2, lang, False)])
Esempio n. 10
0
def degreeRole(semR, env, opts):
    traceSyntR("degreeRole", semR)
    global comp
    comp = ""
    deg = semR.get_concept()
    if deg == "amr-unknown":
        opts.add("b", "how ")
    elif deg == "more":
        opts.add("f", "co")
        comp = "co"
    elif deg == "most":
        opts.add("f", "su")
        comp = "su"
    elif deg == "part":
        env.unshift(Adv("partially"))
    elif deg in ["too", "so", "very", "all", "quite"]:
        env.unshift(Adv(deg))
    elif isAdverb(deg):
        env.push(Adv(deg))
    elif isAdjective(deg):
        env.push(A(deg))
    else:
        env.push(makeSyntR(semR))
Esempio n. 11
0
 def simpleModNoun(concept, neg):  ## check for "simple" cases
     if concept in [
             "all", "many", "both", "no", "too", "any", "other", "some",
             "one", "kind-yy", "then", "such"
     ]:
         env.put(":D", Q("kind of" if concept == "kind-yy" else concept))
         if neg: env.unshift(Q("not"))
         if concept in ["all", "many", "both"]:
             opts.add("n", "p")
     elif concept in determiners:
         env.put(":D", D(concept))
     elif is_number(concept):
         env.push(NO(concept))
     elif isNoun(concept):  ## prefix the :mod for nouns
         newNoun = N(nouns[concept].lemma)  # keep only noun from NP
         if ":A" in env:
             env.insertAfter(":A", ":A", newNoun)
         else:
             env.put(":A", newNoun)
         if neg: env.insertBefore(":A", ":A", Q("non"))
     elif isAdjective(concept):  ## postfix the :mod for adjectives
         newAdj = A(adjectives[concept].lemma)
         if ":A" in env:
             env.insertAfter(":A", ":A", newAdj)
         else:
             env.put(":A", newAdj)
         if neg: env.insertBefore(":A", ":A", Q("non"))
     elif isAdverb(concept):
         env.put(":D", Adv(concept))
     elif isVerb(concept):
         env.push(V(re.sub(r"-\d+$", '', concept)).t("pr"))
     elif semR.roles.areEmpty():  ## equivalent to processSimpleModOther
         env.push(Q(generateConceptWord(concept)))
     else:
         return False
     return True
Esempio n. 12
0
from jsRealBclass import N,A,Adv,V,D,P,C,DT,NO,Q, NP,AP,AdvP,VP,S,PP,CP
from Realization.common import realize, jsrDayPeriod

sky_condition_terminology = { ## types of sky conditions
    "c1":{"en":(AP(A("sunny")),AP(A("clear"))),
          "fr":(AP(A("ensoleillé")),AP(A("dégagé")))},
    "c2":{"en":(AP(Adv("mainly"),A("sunny")),NP(Q("a"),D("few"),N("cloud").n("p"))),
          "fr":(AP(Adv("généralement"),A("ensoleillé")),NP(D("quelque"),N("nuage").n("p")))},
    "c3":{"en":(NP(D("a"),N("mix"),PP(P("of"),CP(C("and"),N("sun"),N("cloud").n("p")))),
                AP(Adv("partly"),A("cloudy"))),
          "fr":(NP(N("alternance"),CP(C("et"),PP(P("de"),N("soleil")),PP(P("de"),N("nuage").n("p")))),
                AP(Adv("partiellement"),A("couvert")))},
    "c4":{"en":(AP(Adv("mainly"),A("cloudy")),),
          "fr":(AP(Adv("généralement"),A("nuageux")),)},
    "c5":{"en":(AP(A("cloudy")),),
          "fr":(AP(A("nuageux")),)},
    "c6":{"en":(AP(A("overcast")),),
          "fr":(AP(A("couvert")),)},
    "c7":{"en":(NP(V("increase").t("pr"),N("cloudiness")),),
          "fr":(NP(N("ennuagement")),)},
    "c8":{"en":(NP(N("clearing")),),
          "fr":(NP(N("dégagement")),)},
}

def sky_condition(mc,period,lang):
    previous_conditions=[]
    jsrExprs=[]

    def addNoRepeat(c,dn,period=None): # avoid generating same sentence twice
        if c not in previous_conditions:
            if len(sky_condition_terminology[c][lang])==1:dn=0
Esempio n. 13
0
         P("en"), N("matinée")))
 },
 "b": {
     "en":
     lambda t, u: S(
         Adv("low"), u.a(","), P("with"),
         temp_trend("en", "rise", t, PP(P("by"), N("morning")))),
     "fr":
     lambda t, u: S(
         N("minimum"), u.a(","),
         temp_trend("fr", "hausse", t, PP(P("en"), N("matinée"))))
 },
 "c": {
     "en":
     lambda t, p: temp_trend("en", "rise", t, p).add(
         AdvP(Adv("then"), A("steady"))),
     "fr":
     lambda t, p: temp_trend("fr", "hausse", t, p).add(
         PP(P("pour"), Adv("ensuite"),
            V("demeurer").t("b"), A("stable")))
 },
 "d": {
     "en":
     lambda t, p: temp_trend("en", "rise", t, p).add(
         AdvP(Adv("then"),
              V("rise").t("pr"), Adv("slowly"))),
     "fr":
     lambda t, p: temp_trend("fr", "hausse", t, p).add(
         AdvP(Adv("puis"), NP(N("hausse"), A("graduel"))))
 },
 "e": {
Esempio n. 14
0
    def showSyntR(syntR):
        print(syntR.show())  # show the indented structure
        print(jsRealB(syntR.show(-1))) # get realized string

    ## a few lexicon entries
    verbs={}
    nouns={}

    verbs['give-01']=LexSem("V","give",[":ARG0",":ARG1",":ARG2"],
                            lambda arg0,arg1,arg2:S(arg0,VP(V("give"),arg1,pp("to",arg2))))    
    nouns['envelope'] = LexSem("envelope","N",[":D",":A"],lambda d,a:NP(optD(d),a,N("envelope")))
    nouns['boy']      = LexSem("boy","N",[":D",":A"],lambda d,a:NP(optD(d),a,N("boy")))
    nouns['girl']     = LexSem("girl","N",[":D",":A"],lambda d,a:NP(optD(d),a,N("girl")))

    boyEnv=Env([(':D',D("a"))])
    boyEnv.put(":A",A("nice")).put(":A",A("little"))
    boySyntR=nouns["boy"].apply(boyEnv,Options([("n","p")]))
    showSyntR(boySyntR) 
# NP(D("a"),
#    A("nice"),
#    A("little"),
#    N("boy")).n("p")
# nice little boys
    
    envelope=nouns["envelope"]
    envelopeSyntR=envelope.apply()
    showSyntR(envelopeSyntR)
# NP(D("the"),
#    N("envelope"))
# the envelope
     
Esempio n. 15
0
# ARG0:giver / ARG1:thing given / ARG2:entity given to [give.xml]
verbs['give-01']=LexSem("give","V",[":ARG0",":ARG1",":ARG2"],
                        lambda arg0,arg1,arg2:S(arg0,VP(V("give"),arg1,pp("to",arg2))))

verbs['know-01']=LexSem("know","V",[":ARG0",":ARG1",":ARG2"], # strangely the lemma is "idk" in PropBank
                        lambda arg0,arg1,arg2:S(arg0,VP(V("know"),arg1,pp("to",arg2))))

## in PropBank : bear-02 :ARG0 should be the "bearer" (e.g. the mother) and :ARG1 the "bearee" 
## but in AMR, :ARG1 is used as the person who is born... without :ARG0
verbs['bear-02']=LexSem("born","V",[":ARG0",":ARG1"],
                        lambda arg0,arg1:S(arg1,VP(V("be"),V("born").t("pp"),pp("to",arg0))))

## in PropBank: hunger-01 :ARG0 corresponds to the person who is hungry (hunger is archaic in this acception)
## so we translate with a more colloquial "be hungry [for...]"
verbs['hunger-01']=LexSem("hunger","V",[":ARG0",":ARG1"],
                          lambda arg0,arg1:S(arg0,VP(V("be"),A("hungry"),pp("for",arg1))))

## correction of prepositions...
# ARG0:buyer / ARG1:thing bought / ARG2:seller / ARG3:price paid / ARG4:benefactive [buy.xml]
verbs['buy-01']=LexSem("buy","V",[":ARG0",":ARG1",":ARG2",":ARG3",":ARG4"],
                  lambda arg0,arg1,arg2,arg3,arg4:S(arg0,VP(V("buy"),arg1,pp("from",arg2),pp("at",arg3),pp("for",arg4))))

#  ARG0:assessor of not failing / ARG1:thing failing / ARG2:task / ARG3:benefactive [fail.xml]
verbs['fail-01']=LexSem("fail","V",[":ARG0",":ARG1",":ARG2",":ARG3"],
                        lambda arg0,arg1,arg2,arg3:S(arg0,arg1,VP(V("fail"),pp("to",arg2),pp("on",arg3))))

# ARG0:pilot, agentive entity capable of flight (like a bird) / ARG1:passenger, cargo / ARG2:aircraft flown, flight number, steed, non-agentive thing in motion / ARG3:type of flight plan, mission, cognate object (like 'a flight' or 'sorties') / ARG4:airline [fly.xml]
verbs['fly-01'] = LexSem("V","fly",[":ARG0",":ARG1",":ARG2",":ARG3",":ARG4"],
                         lambda arg0,arg1,arg2,arg3,arg4:S(arg0,arg1,arg2,VP(V("fly"),arg3,pp("by",arg4))))

## ARG1 <=> ARG2 because of bad parsing of Propbank
Esempio n. 16
0
     "en": Adv("west"),
     "fr": NP(D("le"), N("ouest")),
     "deg": 290
 },
 "ely": {
     "en": Adv("easterly"),
     "fr": NP(D("le"), N("secteur"), N("est")),
     "deg": 90
 },
 "nly": {
     "en": Adv("northerly"),
     "fr": NP(D("le"), N("secteur"), N("nord")),
     "deg": 0
 },
 "nely": {
     "en": A("northeasterly"),
     "fr": NP(D("le"), N("secteur"), N("nord-est")),
     "deg": 45
 },
 "nwly": {
     "en": A("northwesterly"),
     "fr": NP(D("le"), N("secteur"), N("nord-ouest")),
     "deg": 315
 },
 "wly": {
     "en": Adv("westerly"),
     "fr": NP(D("le"), N("secteur"), N("ouest")),
     "deg": 270
 },
 "sly": {
     "en": Adv("southerly"),
Esempio n. 17
0
pp = lambda prep, arg: PP(P(prep), arg) if arg != None else None
optD = lambda det: det if det != None else D("the")

verbs['give-01'] = LexSem(
    "V", "give", [":ARG0", ":ARG1", ":ARG2"],
    lambda arg0, arg1, arg2: S(arg0, VP(V("give"), arg1, pp("to", arg2))))

nouns['envelope'] = LexSem("envelope", "N", [":D", ":A"],
                           lambda d, a: NP(optD(d), a, N("envelope")))
nouns['boy'] = LexSem("boy", "N", [":D", ":A"],
                      lambda d, a: NP(optD(d), a, N("boy")))
nouns['girl'] = LexSem("girl", "N", [":D", ":A"],
                       lambda d, a: NP(optD(d), a, N("girl")))

adjectives["little"] = LexSem("little", "A", [], lambda: A("little"))
adjectives["nice"] = LexSem("nice", "A", [], lambda: A("nice"))

nounInfo = lambda lemma: LexSem(lemma, "N", [":D", ":A"], lambda d, a: NP(
    optD(d), a, N(lemma)))
adjInfo = lambda lemma: LexSem(lemma, "A", [], lambda: A(lemma))


def showSyntR(syntR):
    print(syntR)
    print(syntR.show())
    print(jsRealB(syntR.show(-1)))


def op16(conj):
    return LexSem(
Esempio n. 18
0
                self.opts.append((opt, value))
        else:
            self.opts.append((opt, value))
        return self

    def apply(self, syntR):
        for opt, value in self.opts:
            # adapted from https://stackoverflow.com/questions/3061/calling-a-function-of-a-module-by-using-its-name-a-string
            getattr(syntR, opt)(value)
        return syntR


nounInfo = lambda lemma: LexSem(lemma, "N", [":D", ":A"], lambda d, a: NP(
    optD(d), a, N(lemma)))
adjInfo = lambda lemma: LexSem(
    lemma, "A", [":ARG1"], lambda a1: A(lemma)
    if a1 == None else AP(A(lemma), a1))
pp = lambda prep, arg: PP(P(prep), arg) if arg != None else None
optD = lambda det: det if det != None else D("the")


class LexSem:
    def __init__(self, lemma, pos, args, lambda_):
        self.lemma = lemma
        self.pos = pos
        self.args = args
        self.lambda_ = lambda_

    def __str__(self):
        return "LexSem(%s,%s)" % (self.lemma, self.pos)
Esempio n. 19
0
from jsRealBclass import jsRealB, N,A,Adv,V,D,P,C,DT,NO,Q, NP,AP,AdvP,VP,S,SP,PP,CP
from Realization.common import realize, jsrDayPeriod, jsrHour, get_max_term, get_min_term, get_term_at

precipitationTypes = {
    "showers":{"en":N("shower").n("p"), 
               "fr":N("averse").n("p")},
    "flurries":{"en":N("flurry").n("p"), 
                     "fr":NP(N("averse").n("p"),PP(P("de"),N("neige")))},
    "wet-flurries":{"en":NP(A("wet"),N("flurry").n("p")), 
                              "fr":NP(N("averse").n("p"),PP(P("de"),N("neige"),A("fondant")))},
    "blizzard":{"en":N("blizzard"), 
                "fr":N("blizzard")},
    "snow-squalls":{"en":NP(N("snow"),N("squall").n("p")), 
                         "fr":NP(N("bourrasque").n("p"),PP(P("de"),N("neige")))},
    "drizzle":{"en":N("drizzle"), 
              "fr":N("bruine")},
    "freezing-drizzle" :{"en":NP(V("freeze").t("pr"),N("drizzle")), 
                           "fr":NP(N("bruine"),A("verglaçant"))},
    "ice-crystals" :{"en":NP(N("ice"),N("crystal").n("p")), 
                       "fr":NP(N("cristal").n("p"),PP(P("de"),N("glace")))},
    "hail":{"en":N("hail"), 
             "fr":N("grêle")},
    "ice-pellets":{"en":NP(N("ice"),N("pellet").n("p")), 
              "fr":N("grésil")},
    "snow":{"en":N("snow"), 
             "fr":N("neige")},
    "wet-snow" :{"en":NP(A("wet"),N("snow")), 
                       "fr":NP(N("neige"),N("fondant"))},
    "thunderstorm":{"en":N("thunderstorm"), 
              "fr":N("orage").n("p")},
    "rain":{"en":N("rain"), 
Esempio n. 20
0
from jsRealBclass import jsRealB, N,A,Adv,V,D,P,C,DT,NO,Q, NP,AP,AdvP,VP,S,PP,CP
from Realization.common import realize, jsrDayPeriod, jsrHour, get_max_term, get_min_term, get_term_at

#### UV_index values: info taken from
#  https://www.canada.ca/en/environment-climate-change/services/weather-health/uv-index-sun-safety/about.html
#      Low (0-2), Moderate (3-5), High (6-7), Very High (8-10), and Extreme (11+)
uv_ranges= [(2,   {"en":A("low"),                     "fr":A("bas")}), 
            (5,   {"en":A("moderate"),                "fr":A("modéré")}), 
            (7,   {"en":A("high"),                    "fr":A("élevé")}), 
            (10,  {"en":AP(Adv("very"), A("high")),   "fr":AP(Adv("très"),A("élevé"))}), 
            (1000,{"en":A("extreme"),                 "fr":A("extrême")})]

def uv_index(wInfo,period,lang):
    if period in ["tonight","tomorrow_night"]:      # no UV index during the night
        return None
    uvi_terms=wInfo.get_uv_index(period)
    if uvi_terms==None:return None 
    uvVal=uvi_terms[0].infos[0]                     # consider only the first uvi_term
    if uvVal<1: return None                         # too low
    uvVal=round(uvVal)
    if uvVal==0:return None
    for high,expr in uv_ranges:
        if uvVal<=high:
            return realize(NP(Q("UV index" if lang=="en" else "indice UV"),
                              NO(uvVal),C("or" if lang=="en" else "ou"),expr[lang]),
                           lang)
    return None


if __name__ == '__main__':
    def showEnFr(jsrExprEN,jsrExprFR):