Virgil Dupras avatar Virgil Dupras committed 0cc0096

Phasing out fairware.

Comments (0)

Files changed (6)

 import logging.handlers
 import cherrypy
 
-from .env import Session, tmplenv
-from .model import Developer, Timelog
+from .env import tmplenv
+from .model import Developer
 from .view.developer import DeveloperView
 from .view.project import ProjectView
 from .view.contribution import ContributionView
 from .view.timelog import TimelogView
 from .view.account import AccountView
 from .view.backend import BackendView
-from .view.util import timelog_table
 
 current_dir = op.dirname(op.abspath(__file__))
 
     
     @cherrypy.expose
     def index(self):
-        session = Session()
-        project_table = self.projects.project_table(session)
-        recent_contribs = self.contribs.recent_contributions_table(session)
-        min_timelog_id = session.query(Timelog).all()[-10].id
-        timelogs = Timelog.timelogs_by_date(session.query(Timelog).filter(Timelog.id >= min_timelog_id))
-        timelogs_rendered = timelog_table(timelogs, True, True)
         template = tmplenv.get_template('main.htm')
-        return template.render(project_table=project_table, recent_contribs=recent_contribs,
-            timelogs_table=timelogs_rendered)
+        return template.render()
     
     @cherrypy.expose
     def contribute(self):
 from sqlalchemy.ext.declarative import declarative_base
 
 from .hscommon.util import allsame
-from .env import Session, CURRENCY_RATES
+from .env import Session
 
 # IMPORTANT NOTE: All amounts in all models are integers representing USD *cents* (it makes 
 # everything so much simpler). The only exception to this is PaypalTransaction in which the amounts
     def change_status(self, new_status):
         session = Session.object_session(self)
         self.status = new_status
-        if new_status == 'Completed':
-            if self.contribution is None:
-                rate = CURRENCY_RATES[self.currency]
-                net_amount = round(self.net_amount * rate)
-                gross_amount = round(self.gross_amount * rate)
-                contrib = Contribution(self.date, self.contributor, self.project, net_amount,
-                    gross_amount, self.is_open)
-                session.add(contrib)
-                self.contribution = contrib
-                contrib.allocate() # commits in there
-        else:
-            if self.contribution is not None:
-                self.contribution.remove()
-                self.contribution = None
-                session.commit()
+        session.commit()
+        # We used to create a new Contribution here (when the status was Completed), but we don't
+        # do that anymore.
     
 
 class Cache(Base):

templates/about.htm

 
 > *Free as in speech, Fair as in trade*
 
-"Fairware" is a [term I coined recently](http://www.hardcoded.net/articles/free-as-in-speech-fair-as-in-trade) to designate open source development of software targeting a wide audience (typically published in the form of "Shareware" in the proprietary world) with expectation of fair compensation from users. It's a mix of two driving principles:
+"Fairware" is a [term I coined in 2010](http://www.hardcoded.net/articles/free-as-in-speech-fair-as-in-trade)
+to designate open source development of software targeting a wide audience (typically published in
+the form of "Shareware" in the proprietary world) with expectation of fair compensation from users.
+It's a mix of two driving principles:
 
-**1. Intellectual property doesn't make sense (at least in the software world).** The protection of intellectual property causes much grief all over the world, all the time. Software patents threatens developers at every corner, like land mines. Proprietary licensing makes developers create the same software over and over again in a silly competition game, making the end user suffer in the end (for not having access to the collaborative effort instead of the competitive one). Some users fall in the hands of some unethical software companies that will squeeze every penny they can from them, taking advantage from the fact that they're captive users.
+**1. Intellectual property doesn't make sense (at least in the software world).** The protection of
+intellectual property causes much grief all over the world, all the time. Software patents threatens
+developers at every corner, like land mines. Proprietary licensing makes developers create the same
+software over and over again in a silly competition game, making the end user suffer in the end (for
+not having access to the collaborative effort instead of the competitive one). Some users fall in
+the hands of some unethical software companies that will squeeze every penny they can from them,
+taking advantage from the fact that they're captive users.
 
-**2. Developers have to eat.** It's hard for open source developers doing generic software targeting a wide audience to get compensated for their work. Sure, they may receive some donations from users, but certainly not enough to allow them to work full time on their applications. Because of this, they only work on their open source software in their spare time, and this generally reduces the quality of it. Chances are, if they could, they'd quit their day job and work on their software full time, creating a fair alternative to their proprietary competitors, slowly making intellectual property irrelevant, but money unfortunately flows towards these proprietary software developers, starving the overall open source effort.
+**2. Developers have to eat.** It's hard for open source developers doing generic software targeting
+a wide audience to get compensated for their work. Sure, they may receive some donations from users,
+but certainly not enough to allow them to work full time on their applications. Because of this,
+they only work on their open source software in their spare time, and this generally reduces the
+quality of it. Chances are, if they could, they'd quit their day job and work on their software full
+time, creating a fair alternative to their proprietary competitors, slowly making intellectual
+property irrelevant, but money unfortunately flows towards these proprietary software developers,
+starving the overall open source effort.
 
-**Fairware** is open source software with the assumption that some users are fair. If we can assume that (and I sure hope we can), we can build a system helping them to "express their fairness" (to contribute). With the typical "Donate" button, figuring out what is the fair thing to do is hard, even for a fair user (read [this article](http://www.hardcoded.net/articles/free-as-in-speech-fair-as-in-trade) for more details). Who worked on the project? How many hours? How much did they receive yet? These are all questions that need to be answered before determining a fair amount of money to give to a project. Chances are, even when users are fair, laziness takes over and these users end up not donating, for lack of information to make a correct judgement.
+**Fairware** is open source software with the assumption that some users are fair. If we can assume
+that (and I sure hope we can), we can build a system helping them to "express their fairness" (to
+contribute). With the typical "Donate" button, figuring out what is the fair thing to do is hard,
+even for a fair user (read [this article](http://www.hardcoded.net/articles/free-as-in-speech-fair-as-in-trade)
+for more details). Who worked on the project? How many hours? How much did they receive yet? These
+are all questions that need to be answered before determining a fair amount of money to give to a
+project. Chances are, even when users are fair, laziness takes over and these users end up not
+donating, for lack of information to make a correct judgement.
 
-**How does Fairware work?** All hours developers invest in projects are public, as well as their hourly rate expectations. All contributions from fair users are also instantly made public (anonymously). When contributions are made, they are allocated to unpaid development hours (see the [F.A.Q.](/faq/) for details). Everyone can thus easily know how many hours have yet to be compensated. Also, users are made aware that the software is Fairware with a dialog that pops up for users who haven't contributed yet, reminding them of expectations from developers. With enough fair users, such a system allows open source developers working on software for a wide audience to do so full time. I don't know about you, but I find that **awesome**.
+**How does Fairware work?** All hours developers invest in projects are public, as well as their
+hourly rate expectations. All contributions from fair users are also instantly made public
+(anonymously). When contributions are made, they are allocated to unpaid development hours (see the
+[F.A.Q.](/faq/) for details). Everyone can thus easily know how many hours have yet to be
+compensated. Also, users are made aware that the software is Fairware with a dialog that pops up
+for users who haven't contributed yet, reminding them of expectations from developers. With enough
+fair users, such a system allows open source developers working on software for a wide audience to
+do so full time. I don't know about you, but I find that **awesome**.
 
 **An opt-in system.** After a couple of testing and tweaking of the fairware system, I realized
 that many users didn't want to hear about intellectual property and just wanted to know how much it
 if you want to enable the fairware mode, all you have to do is to open the registration key dialog,
 type "fairware" in any of the two fields and click submit.**
 
-**Being phased out.** Even though I still think it was a neat idea, I'm [phasing it out](http://www.hardcoded.net/articles/phasing-out-fairware)
-starting 2013-03-16.
+**Being phased out.** Even though I still think it was a neat idea, I'm
+[phasing it out](http://www.hardcoded.net/articles/phasing-out-fairware) starting 2013-03-16.
 {% endfilter %}
 {% endblock %}

templates/contriblist.htm

 
 {% block content %}
 
-<p><em>All contributions are in USD and have started on 13/09/2010.</em></p>
+<p>The tables below are contribution statistics from fairware contributions from 13/09/2010 to
+23/03/2013. Amounts are in USD.</p>
 
 {{ contrib_table }}
 
-<h2>Recent contributions</h2>
-
-{{ recent_contribs }}
-
 <h2>Contributions by operating system</h2>
 
 {{ contributions_by_os_table }}
 
-<p><em>Operating system information is incomplete, so these stats represent only a small part of the contributions. But still, it gives an idea...</em></p>
+<p><em>Operating system information is incomplete, so these stats represent only a small part of
+the contributions. But still, it gives an idea...</em></p>
 
 <h2>Contributions by country</h2>
 

templates/main.htm

 
 {% block content %}
 {% filter md %}
-Applications created by Hardcoded Software are open source. However, it needs to be clear that these applications have been *professionally* built and that the time invested in building those applications is expected to be compensated by contributions from users. All hours invested in HS apps are logged, and all contributions are used to pay those hours back. There are more details about how this system works in [the about page](/about/).
+Applications created by Hardcoded Software are open source. They also used to be
+[fairware](/about/), an innovative development model that tried to reconcile "sharware-type" open
+source applications with a "shareware" type of revenue. It was partly successful, but in march 2013,
+after two years and a half of fairware, [I began phasing it out](http://www.hardcoded.net/articles/phasing-out-fairware).
 
-In short, if you use HS applications and that you haven't contributed yet, please consider doing so if there are any unpaid hours for the application you're using.
+HS apps are now "purely" open source or on they way to being so. The only exception is dupeGuru,
+whose transition I'll delay a bit (I explain why in the article linked above).
 
-{{ project_table }}
+This website is here for legacy purposes, that is, to avoid creating dead hyperlinks and to explain
+what fairware has been while it lasted. The [Stats](/contribs/) page will give you contribution
+statistics for those 2.5 years.
 
-*The logging of hours for Fairware started on 13/09/2010*
+Virgil Dupras, Hardcoded Software
 {% endfilter %}
-
-<h2>Recent contributions</h2>
-
-{{ recent_contribs }}
-
-<h2>Latest Timelogs</h2>
-
-{{ timelogs_table }}
-
 {% endblock %}

view/contribution.py

 # http://www.hardcoded.net/licenses/bsd_license
 
 from collections import namedtuple, defaultdict
-from datetime import date, timedelta
 
 from cherrypy import expose, NotFound
 from sqlalchemy import func, desc
         template = tmplenv.get_template('contriblist.htm')
         return template.render(
             contrib_table=self.contributions_table(session),
-            recent_contribs=self.recent_contributions_table(session),
             contributions_by_country_table=self.contributions_by_country_table(session),
             contributions_by_os_table=self.contributions_by_os_table(session))
     
     def contributions_table(self, session):
         t = Table()
         cell_classes = {1: 'rightelem', 2: 'rightelem', 3: 'rightelem'}
-        header = ['Project', 'This Month', 'Last Month', 'Total']
+        header = ['Project', 'Contributions']
         t.add_row(header, is_header=True, cell_classes=cell_classes)
         total_contribs = defaultdict(int)
-        thismonth_contribs = defaultdict(int)
-        lastmonth_contribs = defaultdict(int)
-        thismonth = date.today().strftime('%Y-%m')
-        lastmonth = (date(date.today().year, date.today().month, 1) - timedelta(days=1)).strftime('%Y-%m')
-        grouped_date_func = func.strftime('%Y-%m', Contribution.date)
-        fields = [grouped_date_func, Contribution.project_id, func.sum(Contribution.gross_amount)]
-        group_by = [grouped_date_func, Contribution.project_id]
+        fields = [Contribution.project_id, func.sum(Contribution.gross_amount)]
+        group_by = [Contribution.project_id]
         rows = session.query(*fields).group_by(*group_by).all()
         for row in rows:
-            project_id = row[1]
-            total_contribs[project_id] += row[2]
-            if row[0] == thismonth:
-                thismonth_contribs[project_id] += row[2]
-            elif row[0] == lastmonth:
-                lastmonth_contribs[project_id] += row[2]
+            project_id = row[0]
+            total_contribs[project_id] += row[1]
         for project in session.query(Project).filter_by(hidden=False).all():
             if project.id not in total_contribs:
                 continue
             total = total_contribs[project.id]
-            current = thismonth_contribs[project.id]
-            last = lastmonth_contribs[project.id]
-            rowfmt = [project_link(project), amountfmt(current), amountfmt(last), amountfmt(total)]
+            rowfmt = [project_link(project), amountfmt(total)]
             t.add_row(rowfmt, cell_classes=cell_classes)
         return t.render()
     
     def contributions_by_os_table(self, session):
         t = Table()
         row_cell_classes = {1: 'rightelem', 2: 'rightelem'}
-        header = ['Operating System', '% 30 Days', '% All Time']
+        header = ['Operating System', '%']
         t.add_row(header, is_header=True, cell_classes=row_cell_classes)
         amount_sum = func.sum(Contribution.gross_amount)
         base_query = session.query(Contributor.operating_system, amount_sum)\
             .join(Contribution.contributor).filter(Contributor.operating_system!=None)
-        # 30 days
-        q = base_query.filter(Contribution.date>=date.today()-timedelta(days=30))\
-            .group_by(Contributor.operating_system)
-        data_30days = group_linux_dict({os: amount for os, amount in q.all()})
-        total_30days = sum(data_30days.values())
         q = base_query.group_by(Contributor.operating_system)
         data_all = group_linux_dict({os: amount for os, amount in q.all()})
         total_all = sum(data_all.values())
         for operating_system in sorted(data_all.keys()):
             osdesc = osfmt(operating_system)
-            amount_30days = data_30days[operating_system]
             amount_all = data_all[operating_system]
-            ratio_30days = amount_30days / total_30days
-            ratio_30days_fmt = '{:0.1f} %'.format(ratio_30days * 100)
             ratio_all = amount_all / total_all
             ratio_all_fmt = '{:0.1f} %'.format(ratio_all * 100)
-            t.add_row([osdesc, ratio_30days_fmt, ratio_all_fmt], cell_classes=row_cell_classes)
+            t.add_row([osdesc, ratio_all_fmt], cell_classes=row_cell_classes)
         return t.render()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.