<commit_before>#!/usr/bin/env python

'''
pack -- 
'''

import logging
import operator
import math
import sys

import django.db
import rectpack
from django.core.management.base import BaseCommand

from app.models import SourceFile
from app import render


logging.basicConfig(
    stream=sys.stderr,
    level=logging.DEBUG,
    format='%(asctime)s %(levelname)s %(message)s',
    datefmt='%H:%M:%S'
)
logger = logging.getLogger(__name__)


def box_dimensions(lines):
    dim = math.ceil(math.sqrt(lines))
    return [dim, dim]

def pack(project):
    "pack each file sized according to count of source lines"
    file_data = SourceFile.objects.filter(
        project=project).values_list('path', 'num_lines')
    total_lines = sum(item[1] for item in file_data)
    bin_lines = 2*total_lines # heuristic!
    
    packer = rectpack.newPacker()
    packer.add_bin(*box_dimensions(bin_lines))
    for path,num_lines in file_data:
        packer.add_rect(*box_dimensions(num_lines), rid=path)

    packer.pack()
    # (b, x, y, w, h, rid)
    for pack_info in packer.rect_list():
        print pack_info[1], pack_info[-1]



class Command(BaseCommand):
    help = __doc__

    def add_arguments(self, parser):
        parser.add_argument('projects', nargs='+')
        # parser.add_argument('--project')
        # # parser.add_argument('--tags')

    def handle(self, *args, **options):
        projects = options['projects']
        if projects == ['all']:
            projects = SourceFile.projects()

        for project in projects:
            pack(project)
        # for project_dir in map(os.path.expanduser, options['project_dirs']):
        #     if not os.path.isdir(project_dir):
        #         logger.warning(
        #             '%s: project must be directory, skipping', project_dir)
        #         continue
            
        #     # X: doesn't support multiple dirs
        #     project_name = (options.get('project')
        #         or format_project_name(project_dir))

        #     logger.info('%s: start', project_name)
        #     make_index(project_name, project_dir)

        #     logger.debug('%s: done', project_name)
<commit_msg>wip: pack and render source-sized boxes<commit_after>#!/usr/bin/env python

'''
pack -- 
'''

import logging
import operator
import math
import sys

import django.db
import rectpack
from django.core.management.base import BaseCommand
from bokeh.plotting import figure, show, output_file
# from bokeh.sampledata.iris import flowers

from app.models import SourceFile
from app import render


logging.basicConfig(
    stream=sys.stderr,
    level=logging.DEBUG,
    format='%(asctime)s %(levelname)s %(message)s',
    datefmt='%H:%M:%S'
)
logger = logging.getLogger(__name__)


def box_dimensions(lines):
    dim = math.ceil(math.sqrt(lines))
    return [dim, dim]


# (b, x, y, w, h, rid)

def render(rectangles):
    # import ipdb ; ipdb.set_trace()
    # colormap = {'setosa': 'red', 'versicolor': 'green', 'virginica': 'blue'}
    # colors = [colormap[x] for x in flowers['species']]

    p = figure(title = "Beer Morphology")
    p.xaxis.axis_label = 'Petal Length'
    p.yaxis.axis_label = 'Petal Width'

    for (_, x,y, w,h, path) in rectangles:
        p.rect(x,y, width=w,height=h)
           # color=colors, fill_alpha=0.2, size=10)

    output_file("zoot.html", title="example")

    show(p)

def pack(project):
    "pack each file sized according to count of source lines"
    file_data = SourceFile.objects.filter(
        project=project).values_list('path', 'num_lines')
    total_lines = sum(item[1] for item in file_data)
    bin_lines = 2*total_lines # X: heuristic!
    
    packer = rectpack.newPacker()
    packer.add_bin(*box_dimensions(bin_lines))
    for path,num_lines in file_data[:22]:
        packer.add_rect(*box_dimensions(num_lines), rid=path)

    logger.info('%s: %d rectangles, packing', project, len(file_data))
    packer.pack()
    logger.info('%s: packing done', project)

    render(packer.rect_list())

    # (b, x, y, w, h, rid)
    # for pack_info in packer.rect_list():
    #     print pack_info[1], pack_info[-1]



class Command(BaseCommand):
    help = __doc__

    def add_arguments(self, parser):
        parser.add_argument('projects', nargs='+')
        # parser.add_argument('--project')
        # # parser.add_argument('--tags')

    def handle(self, *args, **options):
        projects = options['projects']
        if projects == ['all']:
            projects = SourceFile.projects()

        for project in projects:
            pack(project)
        # for project_dir in map(os.path.expanduser, options['project_dirs']):
        #     if not os.path.isdir(project_dir):
        #         logger.warning(
        #             '%s: project must be directory, skipping', project_dir)
        #         continue
            
        #     # X: doesn't support multiple dirs
        #     project_name = (options.get('project')
        #         or format_project_name(project_dir))

        #     logger.info('%s: start', project_name)
        #     make_index(project_name, project_dir)

        #     logger.debug('%s: done', project_name)

{'fraction_non_alphanumeric': 0.12971926427879962, 'fraction_numerical': 0.0027105517909002904, 'mean_word_length': 2.8351893095768372, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2222358', 'n_tokens_mistral': 1686, 'n_tokens_neox': 1638, 'n_words': 379}