Beispiel #1
0
class Resource(Place):
    editors = db.ForeignKey(kind="Person", repeated=True)
    name = db.String()
    description = db.Text()
    tags = db.ForeignKey(kind=Tag, repeated=True)
    icon = db.String()  # refers to ctmap graphic resource
    label = "name"

    def _pre_trans_zipcode(self, val):
        if isinstance(val, string_types) and len(val) < 10:
            val = getzip(val).key
        return val

    def total(self):
        return config.ctcomp.ratios.resource

    def oncreate(self):
        zcode = self.zipcode.get()
        addr = "%s, %s, %s" % (self.address, zcode.city, zcode.state)
        self.latitude, self.longitude = address2latlng(addr)

    def notify(self, podname, interested):
        bod = RESOURCE % (podname, self.name, self.description)
        for person in interested:
            send_mail(to=person.email, subject="new message board", body=bod)
Beispiel #2
0
class Document(db.TimeStampedBase):
    owner = db.ForeignKey(kind=Member)
    logo = db.Binary()
    template = db.ForeignKey(kind=Template)
    name = db.String()
    injections = db.JSON()
    assembly = db.JSON()
    declarations = db.JSON()
    pdf = db.String()
    revision = db.Integer(default=0)
    signup_sheet = db.Boolean(default=True)
    table_of_contents = db.Boolean(default=True)
    declaration_page = db.Boolean(default=True)
    pretty_filenames = db.Boolean(default=True)
    section_page_breaks = db.Boolean(default=False)

    def summary(self):
        d = {
            "key": self.id(),
            "name": self.name,
            "revision": self.revision,
            "pdf": self.pdf,
            "created": str(self.created)[:19],
            "modified": str(self.modified)[:19],
            "declarations": self.declarations or {}
        }
        if self.template:
            t = self.template.get()
            d["template"] = {"key": t.id(), "name": t.name}
        return d

    def content(self, sections=None):
        return self.template.get().content(
            sections, page_breaks=self.section_page_breaks)
Beispiel #3
0
class Codebase(db.TimeStampedBase):
    pod = db.ForeignKey(kind="Pod")
    owner = db.String()  # bubbleboy14
    repo = db.String()  # ctcomp
    variety = db.String(choices=[
        "platform", "framework", "service", "research and development"
    ])
    dependencies = db.ForeignKey(kind="Codebase", repeated=True)
    label = "repo"

    def deposit(self, amount, deed):
        log('compensating "%s/%s" codebase: %s' %
            (self.owner, self.repo, amount))
        contz = self.contributions()
        total = float(sum([cont.count for cont in contz]))
        platcut = amount * ratios.code.get(self.variety, ratios.code.rnd)
        log('dividing %s cut (%s) among %s contributors' %
            (self.variety, platcut, len(contz)))
        details = "variety: %s\nowner: %s" % (self.variety, self.owner)
        for contrib in contz:
            memship = contrib.membership()
            memship and memship.deposit(
                platcut * contrib.count / total, deed, "code usage: %s@%s" %
                (contrib.handle(), self.repo), details, True)
        depcut = amount * ratios.code.dependency
        dnum = len(self.dependencies)
        if dnum:
            depshare = depcut / dnum
            log('dividing dependency cut (%s) among %s codebases' %
                (depcut, dnum))
            for dep in db.get_multi(self.dependencies):
                dep.deposit(depshare, deed)

    def contributions(self, asmap=False):
        clist = Contribution.query(Contribution.codebase == self.key).fetch()
        if not asmap:
            return clist
        contz = {}
        for cont in clist:
            contz[cont.contributor.get().handle] = cont
        return contz

    def refresh(self, cbatch):
        from .util import getContribution
        freshies = fetch("api.github.com",
                         "/repos/%s/%s/contributors" % (self.owner, self.repo),
                         asjson=True,
                         protocol="https")
        pcount = 0
        ccount = 0
        for item in freshies:
            log("checking for: %s" % (item["login"], ), 1)
            contrib = getContribution(self, item["login"])
            if contrib:
                pcount += 1
                ccount += contrib.refresh(item["contributions"], cbatch)
        return "%s/%s: %s contributors, %s contributions" % (
            self.owner, self.repo, pcount, ccount)
Beispiel #4
0
class Contactable(db.TimeStampedBase):
    tags = db.ForeignKey(kind=Tag, repeated=True)
    member = db.ForeignKey()
    name = db.String()
    email = db.String()
    phone = db.String()
    address = db.String()
    description = db.Text()  # only required field
    closed = db.Boolean(default=False)
    ongoing = db.Boolean(default=False)
Beispiel #5
0
class Timeslot(db.TimeStampedBase):
    schedule = db.String(choices=[
        "once", "weekly", "daily", "exception", "offday", "monthly (date)",
        "monthly (day)"
    ])
    when = db.DateTime()
    duration = db.Float()  # hours

    def stewardship(self):
        return Stewardship.query(
            Stewardship.timeslots.contains(self.key.urlsafe())).get()

    def task(self):
        return Task.query(Task.timeslots.contains(self.key.urlsafe())).get()

    def slotter(self):
        return self.task() or self.stewardship()

    def beforeedit(self, edits):
        sched = edits.get("sched")
        if sched == "daily" or sched == "weekly" and self.schedule == "once":
            return
        task = self.task()
        task and task.downschedule()

    def beforeremove(self, session):
        slotter = self.slotter()
        if slotter:  # no slotter if slotter is deleting itself....
            slotter.timeslots = list(
                filter(lambda x: x != self.key, slotter.timeslots))
            slotter.put(session)
Beispiel #6
0
class Expense(Verifiable):
    executor = db.ForeignKey(kind="Person")  # reimbursement only
    variety = db.String(choices=["dividend", "reimbursement"])
    amount = db.Float(default=0.1)  # for dividend, split amount * total
    recurring = db.Boolean(default=False)

    def dividend(self):
        pod = self.pod()
        pool = pod.pool.get()
        people = db.get_multi(pod.members())
        div = self.amount * pool.outstanding
        cut = div / len(people)
        for person in people:
            person.wallet.get().deposit(cut, pod, self, "dividend")
        pool.debit(div, pod, self, "dividend")

    # reimbursement requires $$ conversion...
    def reimbursement(self):
        pass

    def fulfill(self):
        if (self.passed and not self.recurring) or not self.verified():
            return False
        getattr(self, self.variety)()
        return True
Beispiel #7
0
class Answer(db.TimeStampedBase):
    prompt = db.String()
    response = db.Text()
    rating = db.Integer()  # 1-5

    def full(self):
        return "\n".join([self.prompt, self.response, str(self.rating)])
Beispiel #8
0
class ZipCode(db.ModelBase):
    code = db.String()
    city = db.String()
    state = db.String()
    county = db.String()
    latitude = db.Float()
    longitude = db.Float()
    label = "code"

    def __str__(self):
        return self.code

    def latlng(self):
        self.latitude, self.longitude = address2latlng(self.code)
        self.put()

    def fullString(self):
        return "%s, %s, %s" % (self.city, self.state, self.code)
Beispiel #9
0
class LibItem(db.TimeStampedBase):
    content = db.ForeignKey(kind="Content")
    editors = db.ForeignKey(kind="Person", repeated=True)
    name = db.String()
    description = db.Text()
    tags = db.ForeignKey(kind=Tag, repeated=True)
    label = "name"

    def notify(self, podname, interested):
        bod = LIBITEM % (podname, self.name, self.description)
        for person in interested:
            send_mail(to=person.email, subject="new message board", body=bod)
Beispiel #10
0
class Task(db.TimeStampedBase):
    editors = db.ForeignKey(repeated=True)
    timeslots = db.ForeignKey(kind=Timeslot, repeated=True)
    commitments = db.ForeignKey(kind=Stewardship, repeated=True)
    name = db.String()
    description = db.Text()
    mode = db.String()  # arbitrary
    requirements = db.String(repeated=True)
    steps = db.String(repeated=True)

    def happening(self, now):
        slots = []
        for slot in db.get_multi(self.timeslots):
            if isDay(slot, now):
                slots.append(slot)
        if len(slots) is 1:  # if 2, one is exception
            return slots[0]

    def unsteward(self, stewardship, verb="rescheduled"):  # just a notifier
        send_mail(to=stewardship.steward.get().email,
                  subject="commitment update",
                  body=RESCHED % (self.name, verb))

    def downschedule(self):
        stewz = db.get_multi(self.commitments)
        for stew in stewz:
            self.unsteward(stew, "rescheduled")
        self.commitments = []
        self.put()
        db.delete_multi(stewz)

    def beforeremove(self, session):
        for stew in db.get_multi(self.commitments, session):
            self.unsteward(stew, "removed")

    def afterremove(self, session):
        db.delete_multi(
            db.get_multi(self.timeslots + self.commitments, session), session)
Beispiel #11
0
class Feedback(db.TimeStampedBase):
    person = db.ForeignKey(kind=Person)
    conversation = db.ForeignKey(kind=Conversation)
    interaction = db.ForeignKey(kinds=[Appointment, Delivery, Request])
    answers = db.ForeignKey(kind=Answer, repeated=True)
    topic = db.String()
    notes = db.Text()
    followup = db.Boolean(default=False)

    def membership(self):
        from .util import membership
        return membership(self.person.get(), self.pod())

    def pod(self):
        return self.interaction.get().pod()

    def full(self):
        answers = "\n\n".join([a.full() for a in db.get_multi(self.answers)])
        return "\n\n".join([
            self.topic, answers, self.notes,
            "request follow up: %s" % (self.followup, )
        ])

    def notify(self):
        bod = FEEDBACK % (self.person.get().firstName, self.pod().name,
                          self.full(), self.key.urlsafe())
        self.interaction.get().notify("feedback", lambda signer: bod,
                                      self.participants())

    def participants(self):
        pars = self.interaction.get().signers()
        if self.person not in pars:
            return pars + [self.person]
        return pars

    def oncreate(self):
        convo = Conversation(topic=self.topic)
        convo.participants = self.participants()
        convo.put()
        self.conversation = convo.key
        self.put()  # for notify() key
        self.notify()
        if self.followup:
            req = Request()
            req.membership = self.membership().key
            req.change = "conversation"
            req.notes = self.notes
            req.put()
            req.remind()
Beispiel #12
0
class Race(db.ModelBase):
    draw_num = db.Integer()
    draw_date = db.DateTime()
    win_num = db.Integer()
    win_name = db.String()
    place_num = db.Integer()
    place_name = db.String()
    show_num = db.Integer()
    show_name = db.String()
    race_time = db.String()

    def data(self):
        return {
            "key": self.key.urlsafe(),
            "draw_date": str(self.draw_date),
            "draw_num": self.draw_num,
            "win_num": self.win_num,
            "win_name": self.win_name,
            "place_num": self.place_num,
            "place_name": self.place_name,
            "show_num": self.show_num,
            "show_name": self.show_name,
            "race_time": self.race_time
        }
Beispiel #13
0
class Update(db.TimeStampedBase):
    sender = db.ForeignKey()
    subject = db.String()
    message = db.Text()
    recipients = db.ForeignKey(repeated=True)
    conversation = db.ForeignKey(kind=Conversation)
    label = "subject"

    def oncreate(self):
        convo = Conversation(topic=self.subject)
        convo.put()
        self.conversation = convo.key
        if self.recipients:
            recipients = db.get_multi(self.recipients)
        else:
            recipients = Member.query().all()
        bod = UPDATE % (self.sender.get().email, self.message)
        for recip in recipients:
            send_mail(to=recip.email, subject=self.subject, body=bod)
Beispiel #14
0
class SecBase(db.TimeStampedBase):
    name = db.String()
    description = db.Text()
    sections = db.ForeignKey(kind="section", repeated=True)

    def secs(self, sections=None, depth=0, novars=False, page_breaks=False):
        return "\r\n\r\n".join(sections and [
            db.get(s['key']).content(s['sections'], depth, novars, page_breaks)
            for s in sections
        ] or [
            s.content(depth=depth, novars=novars, page_breaks=page_breaks)
            for s in db.get_multi(self.sections)
        ])

    def fixed_desc(self, depth=0, novars=False):
        d = self.description
        return h2l(novars and d.replace("{{", "(").replace("}}", ")") or d,
                   depth)

    def desc(self, depth=0, novars=False):
        return self.fixed_desc(depth, novars)

    def header(self):
        return self.name

    def body(self, depth, novars=False, page_breaks=False):
        tline = "%s %s" % ("#" * depth, self.header())
        if page_breaks and depth == 1:
            tline = "\\newpage%s" % (tline, )
        return "%s\r\n\r\n%s" % (tline, self.desc(depth, novars))

    def content(self, sections=None, depth=0, novars=False, page_breaks=False):
        body = self.body(depth, novars, page_breaks)
        secs = self.sections and self.secs(sections, depth + 1, novars,
                                           page_breaks) or ""
        cont = "%s\r\n\r\n%s" % (body, secs)
        log(cont)
        return cont

    def unrolled(self):
        d = self.data()
        d['sections'] = [s.unrolled() for s in db.get_multi(self.sections)]
        return d
Beispiel #15
0
class Invitation(db.TimeStampedBase):
    membership = db.ForeignKey(kind=Membership)
    email = db.String()
    notes = db.Text()

    def invite(self):
        memship = self.membership.get()
        send_mail(to=self.email,
                  subject="invitation",
                  body=INVITATION %
                  (memship.person.get().email, memship.pod.get().name))

    def send(self, person):
        req = Request()
        req.membership = self.membership
        req.person = person.key
        req.change = "include"
        req.notes = self.notes
        req.put()
        req.remind()
Beispiel #16
0
class Adjustment(Proposal):
    variety = db.String()  # already has name!
    compensation = db.Float(default=1.0)

    def oncreate(self):
        convo = Conversation(topic=self.name)
        convo.put()
        self.conversation = convo.key
        service = self.service()
        self.notify(
            "compensation adjustment proposed", lambda signer: ADJUSTMENT %
            (self.name, self.variety, service.compensation, self.compensation,
             self.description))

    def onpass(self):
        serv = self.service()
        self.notify(
            "compensation adjustment approved", lambda signer: ADJUSTED %
            (self.name, self.variety, serv.compensation, self.compensation,
             self.description))
        serv.compensation = self.compensation
        serv.put()

    def notify(self, subject, body):
        for signer in self.voters():
            send_mail(to=signer.get().email,
                      subject=subject,
                      body=body(signer))

    def service(self):
        return Service.query(Service.name == self.name,
                             Service.variety == self.variety).get()

    def voters(self):
        peeps = set()
        for pod in Pod.query(Pod.variety == self.variety).all():
            peeps.update([k.urlsafe() for k in pod.members()])
        return [db.KeyWrapper(p) for p in list(peeps)]

    def votership(self):
        return len(self.voters())
Beispiel #17
0
class Board(db.TimeStampedBase):
    name = db.String()
    description = db.Text()
    anonymous = db.Boolean(default=False)
    tags = db.ForeignKey(kind=Tag, repeated=True)
    conversation = db.ForeignKey(kind=Conversation)
    label = "name"

    def pod(self):
        from .core import Pod
        return Pod.query(Pod.boards.contains(self.key.urlsafe())).get()

    def notify(self, podname, interested):
        bod = BOARD % (podname, self.name, self.description)
        for person in interested:
            send_mail(to=person.email, subject="new message board", body=bod)

    def oncreate(self):
        convo = Conversation(topic=self.name)
        convo.anonymous = self.anonymous
        convo.put()
        self.conversation = convo.key
Beispiel #18
0
class Person(Member):
    ip = db.String()  # optional
    wallet = db.ForeignKey(kind=Wallet)  # optional
    interests = db.ForeignKey(kind=Tag, repeated=True)
    contributors = db.ForeignKey(kind=Contributor, repeated=True)
    chat = db.Boolean(default=True)
    remind = db.Boolean(default=True)

    def onjoin(self):
        from .util import global_pod
        email_admins("New Person", self.email)
        self.enroll(global_pod())
        wallet = Wallet()
        wallet.put()
        self.wallet = wallet.key
        self.put()
        self.process_invites()

    def process_invites(self):
        log("processing invitations for %s" % (self.email, ))
        podz = set()
        for invitation in Invitation.query(
                Invitation.email == self.email).fetch():
            imem = invitation.membership.get()
            ipod = imem.pod.get().name
            memem = imem.person.get().email
            log("pod: %s. inviter: %s" % (ipod, memem), 1)
            if ipod in podz:
                log("skipping invitation -- already invited to pod", 2)
            else:
                log("sending invitation", 2)
                podz.add(ipod)
                invitation.send(self)

    def help_match(self,
                   item):  # overrides Member.help_match() in ctcoop.model
        from .util import membership, reg_act
        which = item.polytype
        isneed = which == "need"
        pod = Pod.query(
            getattr(Pod, which + "s").contains(item.key.urlsafe())).get()
        reg_act(
            membership(self, pod).key, pod.support_service(),
            [isneed and self.key or item.member],
            [isneed and item.member or self.key], item.description)

    def enroll(self, pod):
        from .util import membership
        memship = membership(self, pod)
        if not memship:
            memship = Membership(pod=pod.key, person=self.key)
            memship.put()
        return memship.key

    def tasks(self):
        return db.get_multi(sum([p.tasks for p in self.pods()], []))

    def pods(self):
        return db.get_multi([m.pod for m in self.memberships()])

    def memberships(self):
        return Membership.query(Membership.person == self.key).fetch()

    def acts(self):
        yesterday = datetime.now() - timedelta(1)
        return sum([
            Act.query(Act.membership == m.key,
                      Act.created > yesterday).fetch()
            for m in self.memberships()
        ], [])

    def commitments(self):
        return sum([
            Commitment.query(Commitment.membership == m.key).fetch()
            for m in self.memberships()
        ], [])
Beispiel #19
0
class Payment(db.TimeStampedBase):
    member = db.ForeignKey(kind=Member)
    successful = db.Boolean(default=False)
    amount = db.String()
    duration = db.Integer()  # days
    message = db.Text()
Beispiel #20
0
class Chemical(db.TimeStampedBase):
    classification = db.String()
    code = db.String()
    name = db.String()
    cas = db.String()
    rtecs = db.String()
    dot = db.String()
    idlh = db.String()
    synonyms_and_trade_names = db.String()
    formula = db.String()
    conversion = db.String()
    physical_description = db.String()
    molecular_weight = db.String()
    boiling_point = db.String()
    melting_point = db.String()
    freezing_point = db.String()
    solubility = db.String()
    vapor_pressure = db.String()
    ionization_potential = db.String()
    specific_gravity = db.String()
    flash_point = db.String()
    upper_explosive_limit = db.String()
    lower_explosive_limit = db.String()
    incompatibilities_and_reactivities = db.String()
    exposure_routes = db.String()
    symptoms = db.String()
    target_organs = db.String()
    cancer_site = db.String()
    respirator_recommendations = db.Text()
    exposure_limits = db.Text()
    measurement_methods = db.Text()
    first_aid = db.Text()
    personal_protection_sanitation = db.Text()

    def basic(self):
        return {"key": self.id(), "name": self.name}
Beispiel #21
0
class Table(db.TimeStampedBase):
    name = db.String()
    csv = db.Binary()
Beispiel #22
0
class Survey(db.TimeStampedBase):
    user = db.ForeignKey(kind=CTUser)
    demographics = db.ForeignKey(kind=Demographic, repeated=True)
    title = db.String()
    blurb = db.Text()
    instructions = db.Text()
Beispiel #23
0
class Injection(db.TimeStampedBase):
    name = db.String()
    variety = db.String(choices=["text", "text block"])

    def labeler(self):
        return "%s (%s)" % (self.name, self.variety)
Beispiel #24
0
class Tag(db.TimeStampedBase):
    name = db.String()
Beispiel #25
0
class Pod(db.TimeStampedBase):
    name = db.String()
    variety = db.String()
    blurb = db.Text()
    pool = db.ForeignKey(kind=Wallet)
    agent = db.ForeignKey(kind="Pod")
    needs = db.ForeignKey(kind=Need, repeated=True)
    tasks = db.ForeignKey(kind=Task, repeated=True)
    boards = db.ForeignKey(kind=Board, repeated=True)
    updates = db.ForeignKey(kind=Update, repeated=True)
    drivers = db.ForeignKey(kind=Person, repeated=True)
    includers = db.ForeignKey(kind=Person, repeated=True)
    resources = db.ForeignKey(kind=Resource, repeated=True)
    offerings = db.ForeignKey(kind=Offering, repeated=True)
    dependencies = db.ForeignKey(kind=Codebase, repeated=True)  # software
    library = db.ForeignKey(kinds=[Organization, Book, Web, Media],
                            repeated=True)  # support

    def _trans_boards(self, val):
        v = val[-1].get()
        v.notify(self.name, self.interested(v.tags))
        return val

    def _trans_library(self, val):
        v = val[-1].get()
        v.notify(self.name, self.interested(v.tags))
        return val

    def _trans_resources(self, val):
        v = val[-1].get()
        v.notify(self.name, self.interested(v.tags))
        return val

    def _trans_needs(self, val):
        self.notify(val[-1].get(), NEED)
        return val

    def _trans_offerings(self, val):
        self.notify(val[-1].get(), OFFERING)
        return val

    def notify(self, item, etemp):
        bod = etemp % (self.name, item.description)
        for person in self.interested(item.tags):
            send_mail(to=person.email,
                      subject="new %s" % (item.polytype, ),
                      body=bod)

    def interested(self, tags):
        tagz = set(map(lambda t: t.urlsafe(), tags))
        return filter(
            lambda p: tagz.intersection(
                set(map(lambda t: t.urlsafe(), p.interests))),
            db.get_multi(self.members()))

    def oncreate(self):
        email_admins("New Pod",
                     "name: %s\nvariety: %s" % (self.name, self.variety))
        if not self.pool:
            w = Wallet()
            w.put()
            self.pool = w.key

    def codebases(self):
        return Codebase.query(Codebase.pod == self.key).fetch()

    def _collection(self, mod):
        return sum([
            mod.query(mod.membership == m.key).fetch()
            for m in self.members(True)
        ], [])

    def expenses(self):
        return self._collection(Expense)

    def acts(self):
        return self._collection(Act)

    def requests(self):
        return self._collection(Request)

    def commitments(self):
        return self._collection(Commitment)

    def proposals(self):
        return sum([m.proposals for m in self.members(True)], [])

    def members(self, noperson=False):
        mems = Membership.query(Membership.pod == self.key).fetch()
        return noperson and mems or [mem.person for mem in mems]

    def deposit(self,
                member,
                amount,
                deed,
                note,
                details=None,
                nocode=False,
                pay=False):
        memwall = member.wallet.get()
        if pay:
            memcut = amount * ratios.pay
            amount -= memcut
            memwall.deposit(memcut, self, deed, note, details)
        else:
            memwall.deposit(amount, self, deed, note, details)
        self.pool.get().deposit(amount, self, deed, note, details)
        self.agent and self.agent.get().pool.get().deposit(
            amount * ratios.agent, self, deed, note, details)
        if not nocode:
            for codebase in self.codebases():
                codebase.deposit(amount, deed)
            depcut = amount * ratios.code.dependency
            for dependency in db.get_multi(self.dependencies):
                dependency.deposit(depcut, deed)

    def service(self, member, service, recipient_count, details):
        self.deposit(member, service.compensation * recipient_count, service,
                     "service: %s (%s)" % (service.name, service.variety),
                     details)

    def support_service(self):
        sname = (self.variety == "support") and self.name or "support"
        service = Service.query(Service.name == sname,
                                Service.variety == self.variety).get()
        if not service:
            service = Service(name=sname, variety=self.variety)
            service.put()
        return service.key
Beispiel #26
0
class Service(db.TimeStampedBase):
    name = db.String()
    variety = db.String()
    compensation = db.Float(default=1.0)
Beispiel #27
0
class Content(db.TimeStampedBase):
    membership = db.ForeignKey(kind=Membership)
    memberships = db.ForeignKey(kind=Membership, repeated=True)
    identifier = db.String()  # some hash, defaulting to url
Beispiel #28
0
class Member(CTUser):
    roles = db.String(repeated=True)

    def help_match(self, need_or_offer):
        pass
Beispiel #29
0
class Photo(db.TimeStampedBase):
    img = db.Binary()
    caption = db.String()
    label = "caption"
Beispiel #30
0
class BasePost(db.TimeStampedBase):
    user = db.ForeignKey()  # CTUser, Author, or whatever else
    live = db.Boolean(default=False)
    title = db.String()
    blurb = db.String()
    tags = db.String(repeated=True)