text:
/*global define*/
/*jslint white:true,browser:true*/

define([
    'require',
    'bluebird',
    'uuid',
    'base/js/namespace',
    'common/runtime',
    'common/events',
    'common/html',
    'common/props',
    'common/jupyter',
    'common/busEventManager',
    'kb_service/client/narrativeMethodStore',
    'kb_service/utils',
    'kb_sdk_clients/genericClient',
    'common/pythonInterop',
    'common/utils',
    'common/ui',
    'common/fsm',
    'common/spec',
    'google-code-prettify/prettify',
    './fsm',
    './loading',
    './message',

    'css!google-code-prettify/prettify.css',
    'css!font-awesome.css'
], function(
    require,
    Promise,
    Uuid,
    Jupyter,
    Runtime,
    Events,
    html,
    Props,
    JupyterProxy,
    BusEventManager,
    NarrativeMethodStore,
    serviceUtils,
    GenericClient,
    PythonInterop,
    utils,
    Ui,
    Fsm,
    Spec,
    PR,
    editorCellFsm,
    loadingWidget,
    MessageWidget
) {
    'use strict';
    var t = html.tag,
        div = t('div'),
        span = t('span'),
        a = t('a'),
        p = t('p'),
        table = t('table'),
        tr = t('tr'),
        th = t('th'),
        td = t('td'),
        appStates = editorCellFsm.fsm;

    function CancellationError(message, reason) {
        this.message = message;
        this.reason = reason;
    }
    CancellationError.prototype = Object.create(Error.prototype);
    CancellationError.prototype.constructor = CancellationError;
    CancellationError.prototype.name = 'ClientException';

    function factory(config) {
        var cell = config.cell,
            parentBus = config.bus,

            hostNode, container, ui,
            workspaceInfo = config.workspaceInfo,
            runtime = Runtime.make(),

            // TODO: the cell bus should be created and managed through main.js,
            // that is, the extension.
            cellBus,
            bus = runtime.bus().makeChannelBus({ description: 'An editor cell widget' }),
            env = {},
            editorState,
            model,
            eventManager = BusEventManager.make({
                bus: runtime.bus()
            }),
            // HMM. Sync with metadata, or just keep everything there?
            settings = {
                showAdvanced: {
                    label: 'Show advanced parameters',
                    defaultValue: false,
                    type: 'custom'
                },
                showNotifications: {
                    label: 'Show the notifications panel',
                    defaultValue: false,
                    type: 'toggle',
                    element: 'notifications'
                }
            },
            widgets = {},
            spec,
            fsm;

        if (runtime.config('features.developer')) {
            settings.showDeveloper = {
                label: 'Show developer features',
                defaultValue: false,
                type: 'toggle',
                element: 'developer-options'
            };
        }

        // DATA API

        /*
         * Fetch the app spec for a given app and store the spec in the model.
         * As well, process and store the parameters in the model as well.
         *
         * @param {type} appId
         * @param {type} appTag
         * @returns {unresolved}
         */
        function syncAppSpec(appId, appTag) {
            env.appId = appId;
            env.appTag = appTag;
            var appRef = {
                    ids: [appId],
                    tag: appTag
                },
                nms = new NarrativeMethodStore(runtime.config('services.narrative_method_store.url'), {
                    token: runtime.authToken()
                });

            return nms.get_method_spec(appRef)
                .then(function(data) {
                    if (!data[0]) {
                        throw new Error('App not found');
                    }
                    // TODO: really the best way to store state?
                    env.appSpec = data[0];
                    // Get an input field widget per parameter
                });
        }

        // RENDER API

        function syncFatalError() {
            ui.setContent('fatal-error.title', editorState.getItem('fatalError.title'));
            ui.setContent('fatal-error.message', editorState.getItem('fatalError.message'));
            ui.setContent('fatal-error.details', editorState.getItem('fatalError.details'));
            ui.setContent('fatal-error.advice', editorState.getItem('fatalError.advice'));
        }

        function showFatalError(arg) {
            ui.showElement('fatal-error');
        }

        function renderSetting(settingName) {
            var setting = settings[settingName],
                value;

            if (!setting) {
                return;
            }

            value = editorState.getItem(['user-settings', settingName], setting.defaultValue);
            switch (setting.type) {
                case 'toggle':
                    if (value) {
                        ui.showElement(setting.element);
                    } else {
                        ui.hideElement(setting.element);
                    }
                    break;
            }
        }

        function toBoolean(value) {
            if (value && value !== null) {
                return true;
            }
            return false;
        }

        function buildLayout(events) {
            var readOnlyStyle = {};
            if (Jupyter.narrative.readonly) {
                readOnlyStyle.display = 'none';
            }
            return div({ class: 'kbase-extension kb-editor-cell', style: { display: 'flex', alignItems: 'stretch' } }, [
                div({ class: 'prompt', dataElement: 'prompt', style: { display: 'flex', alignItems: 'stretch', flexDirection: 'column' } }, [
                    div({ dataElement: 'status' })
                ]),
                div({
                    class: 'body',
                    dataElement: 'body',
                    style: { display: 'flex', alignItems: 'stretch', flexDirection: 'column', flex: '1' }
                }, [
                    div({ dataElement: 'widget', style: { display: 'block', width: '100%' } }, [
                        div({ class: 'container-fluid' }, [
                            ui.buildPanel({
                                title: 'Error',
                                name: 'fatal-error',
                                hidden: true,
                                type: 'danger',
                                classes: ['kb-panel-container'],
                                body: div([
                                    table({ class: 'table table-striped' }, [
                                        tr([
                                            th('Title'), td({ dataElement: 'title' })
                                        ]),
                                        tr([
                                            th('Message'), td({ dataElement: 'message' })
                                        ]),
                                        tr([
                                            th('Details'), td({ dataElement: 'details' })
                                        ])
                                    ])
                                ])
                            }),
                            ui.buildPanel({
                                title: 'Cell Settings',
                                name: 'settings',
                                hidden: true,
                                type: 'default',
                                classes: ['kb-panel-container'],
                                body: div({ dataElement: 'content' })
                            }),
                            ui.buildCollapsiblePanel({
                                title: 'Notifications',
                                name: 'notifications',
                                hidden: true,
                                type: 'default',
                                classes: ['kb-panel-container'],
                                body: [
                                    div({ dataElement: 'content' })
                                ]
                            }),
                            ui.buildCollapsiblePanel({
                                title: 'Dev',
                                name: 'developer-options',
                                hidden: true,
                                type: 'default',
                                classes: ['kb-panel-container'],
                                body: [
                                    div({ dataElement: 'fsm-display', style: { marginBottom: '4px' } }, [
                                        span({ style: { marginRight: '4px' } }, 'FSM'),
                                        span({ dataElement: 'content' })
                                    ]),
                                    div([
                                        ui.makeButton('Show Code', 'toggle-code-view', { events: events }),
                                        ui.makeButton('Edit Metadata', 'edit-cell-metadata', { events: events }),
                                        ui.makeButton('Edit Notebook Metadata', 'edit-notebook-metadata', { events: events })
                                    ])
                                ]
                            }),
                            ui.buildCollapsiblePanel({
                                title: 'Select Object to Edit',
                                name: 'edit-object-selector',
                                hidden: false,
                                type: 'default',
                                classes: ['kb-panel-container'],
                                body: div({ dataElement: 'widget' })
                            }),
                            ui.buildCollapsiblePanel({
                                title: span(['Currently Editing ', span({
                                    dataElement: 'name',
                                    style: {
                                        textDecoration: 'underline'
                                    }
                                })]),
                                name: 'currently-editing',
                                collapsed: true,
                                hidden: false,
                                type: 'default',
                                classes: ['kb-panel-container'],
                                body: div({ dataElement: 'widget' })
                            }),
                            ui.buildPanel({
                                title: span({ class: 'fa fa-pencil', style: { marginLeft: '3px', width: '20px' } }) + 'Editor ',
                                name: 'editor',
                                hidden: false,
                                type: 'default',
                                classes: ['kb-panel-container'],
                                body: div({ dataElement: 'widget' })
                            }),
                            div({
                                dataElement: 'available-actions',
                                style: readOnlyStyle
                            }, [
                                div({ class: 'btn-toolbar kb-btn-toolbar-cell-widget' }, [
                                    div({ class: 'btn-group' }, [
                                        ui.makeButton('Save', 'save', { events: events, type: 'primary' }),
                                        div({
                                            dataElement: 'status',
                                            class: 'xbtn ',
                                            style: {
                                                display: 'inline-block',
                                                marginLeft: '6px',
                                                xborder: '1px red dotted',
                                                padding: '6px 12px',
                                                lineHeight: '1.43'

                                            }
                                        })
                                    ])
                                ])
                            ])
                        ])
                    ])
                ])
            ]);
        }

        function validateModel() {
            return spec.validateModel(model.getItem('params'));
        }

        function setStatus(message) {
            ui.setContent('available-actions.status', message);
        }

        // TODO: we need to determine the proper forms for a app identifier, and
        // who creates this canonical identifier. E.g. the method panel supplies
        // the app id to the cell, but it gets it from the kernel, which gets it
        // directly from the nms/catalog. If the catalog provides the version
        // for a beta or release tag ...
        function fixApp(app) {
            switch (app.tag) {
                case 'release':
                    {
                        return {
                            id: app.id,
                            tag: app.tag,
                            version: app.version
                        };
                    }
                case 'beta':
                case 'dev':
                    return {
                        id: app.id,
                        tag: app.tag
                    };
                default:
                    throw new Error('Invalid tag for app ' + app.id);
            }
        }

        function buildPython() {
            var cellId = utils.getCellMeta(cell, 'kbase.attributes.id');
            var app = editorState.getItem('app');
            var params = modelToParams();
            var runId = editorState.getItem('editorState.currentRunId');

            var fixedApp = fixApp(app);
            var code = PythonInterop.buildEditorRunner(cellId, runId, fixedApp, params);
            // TODO: do something with the runId

            // setStatus('Successfully built code');

            cell.set_text(code);
        }

        function resetPython(cell) {
            cell.set_text('');
        }

        function initializeFSM() {
            var currentState = editorState.getItem('fsm.currentState');
            if (!currentState) {
                // TODO: evaluate the state of things to try to guess the state?
                // Or is this just an error unless it is a new cell?
                // currentState = {mode: 'editing', params: 'incomplete'};
                currentState = { mode: 'new' };
            }
            fsm = Fsm.make({
                states: appStates,
                initialState: {
                    mode: 'new'
                },
                //xinitialState: {
                //    mode: 'editing', params: 'incomplete'
                //},
                onNewState: function(fsm) {
                    editorState.setItem('fsm.currentState', fsm.getCurrentState().state);
                    // save the narrative!

                },
                bus: bus
            });
            fsm.start(currentState);
        }

        // LIFECYCYLE API

        function initCodeInputArea() {
            editorState.setItem('user-settings.showCodeInputArea', false);
        }

        function showCodeInputArea() {
            var codeInputArea = cell.input.find('.input_area').get(0);
            if (editorState.getItem('user-settings.showCodeInputArea')) {
                if (!codeInputArea.classList.contains('-show')) {
                    codeInputArea.classList.add('-show');
                }
            } else {
                if (codeInputArea.classList.contains('-show')) {
                    codeInputArea.classList.remove('-show');
                }
            }
        }

        function toggleCodeInputArea(cell) {
            if (editorState.getItem('user-settings.showCodeInputArea')) {
                editorState.setItem('user-settings.showCodeInputArea', false);
            } else {
                editorState.setItem('user-settings.showCodeInputArea', true);
            }
            showCodeInputArea();
            return editorState.getItem('user-settings.showCodeInputArea');
        }

        function doRemoveNotification(index) {
            var notifications = editorState.getItem('notifications') || [];
            notifications.splice(index, 1);
            editorState.setItem('notifications', notifications);
            renderNotifications();
        }

        function renderNotifications() {
            var events = Events.make(),
                notifications = editorState.getItem('notifications') || [],
                content = notifications.map(function(notification, index) {
                    return div({ class: 'row' }, [
                        div({ class: 'col-md-10' }, notification),
                        div({ class: 'col-md-2', style: { textAlign: 'right' } }, span({}, [
                            a({
                                class: 'btn btn-default',
                                id: events.addEvent({
                                    type: 'click',
                                    handler: function() {
                                        doRemoveNotification(index);
                                    }
                                })
                            }, 'X')
                        ]))
                    ]);
                }).join('\n');
            ui.setContent('notifications.content', content);
            events.attachEvents(container);
        }

        function addNotification(notification) {
            var notifications = editorState.getItem('notifications') || [];
            notifications.push(notification);
            editorState.setItem('notifications', notifications);
            renderNotifications();
        }

        function clearNotifications() {
            editorState.setItem('notifications', []);
        }

        // WIDGETS

        function showWidget(name, widgetModule, path) {
            var bus = runtime.bus().makeChannelBus({ description: 'Bus for showWidget' }),
                widget = widgetModule.make({
                    bus: bus,
                    workspaceInfo: workspaceInfo
                });
            widgets[name] = {
                path: path,
                module: widgetModule,
                instance: widget
            };
            widget.start();
            bus.emit('attach', {
                node: ui.getElement(path)
            });
        }

        /*
         *
         * Render the UI according to the FSM
         */
        function renderUI() {
            renderNotifications();
            var state = fsm.getCurrentState();

            // Button state
            state.ui.buttons.enabled.forEach(function(button) {
                ui.enableButton(button);
            });
            state.ui.buttons.disabled.forEach(function(button) {
                ui.disableButton(button);
            });

            // Element state
            state.ui.elements.show.forEach(function(element) {
                ui.showElement(element);
            });
            state.ui.elements.hide.forEach(function(element) {
                ui.hideElement(element);
            });

            // Editor state flags
            // *** disabling this vew model style
            // ['touched', 'changed'].forEach(function(flag) {
            //     var flagged, params = model.getItem('params');
            //     if (params) {
            //         Object.keys(params).forEach(function(key) {
            //             var param = params[key];
            //             if (param[flag]) {
            //                 flagged = true;
            //             }
            //         });
            //         setStatusFlag(flag, flagged);
            //     }
            // });
            ui.setContent('flags.fsm', JSON.stringify(fsm.getCurrentState().state));

        }

        // var saveTimer = null;

        // function saveNarrative() {
        //     if (saveTimer) {
        //         return;
        //     }
        //     saveTimer = window.setTimeout(function() {
        //         saveTimer = null;
        //         Jupyter.saveNotebook();
        //     }, saveMaxFrequency);
        // }

        function doDeleteCell() {
            var content = div([
                p([
                    'Deleting this cell will remove the editor from the Narrative, ',
                    'but will not delete the associated Reads Sets, which will still be avaiable ',
                    'in the data panel.'
                ]),
                p('Continue to delete this cell?')
            ]);
            ui.showConfirmDialog({ title: 'Confirm Cell Deletion', body: content })
                .then(function(confirmed) {
                    if (!confirmed) {
                        return;
                    }

                    bus.emit('stop');

                    JupyterProxy.deleteCell(cell);
                });
        }

        function doSave() {
            setStatus(html.loading('Saving...'));
            // We stamp the run id and rebuild the code to capture the run id.
            // This is a provides for a sanity check tht the response from the
            // save originates with this request.
            editorState.setItem('editorState.currentRunId', new Uuid(4).format());
            buildPython();
            doSaveReadsSet()
                .then(function() {
                    // Clear the parameter flags
                    // clearModelFlags();
                    renderUI();
                })
                .catch(function(err) {
                    console.error('ERROR!', err);
                });
        }

        function modelToParams() {
            return [{
                workspace: workspaceInfo.id,
                output_object_name: model.getItem('params.name'),
                data: {
                    description: model.getItem('params.description'),
                    items: model.getItem('params.items', []).map(function(item) {
                        return {
                            label: item.label,
                            ref: item.ref
                        };
                    })
                }
            }];
        }

        // TODO: this should be a the error area -- and we should switch the
        // editor into error mode.
        function loadErrorWidget(error) {
            console.error('ERROR', error);
            console.error(error.detail.replace('\n', '<br>'));
            var detail;
            if (error.detail) {
                detail = error.detail.replace('\n', '<br>');
            } else {
                detail = '';
            }

            var content = div({
                style: { border: '1px red solid' }
            }, [
                div({ style: { color: 'red' } }, 'Error'),
                table({
                    class: 'table table-bordered'
                }, [
                    tr([
                        th('Type'), td(error.name || 'Unknown')
                    ]),
                    tr([
                        th('Message'), td(error.message || '')
                    ]),
                    tr([
                        th('Details'), td(error.detail.replace('\n', '<br>'))
                    ])
                ])
            ]);

            ui.setContent('editor.widget', content);
        }

        function setStatusFlag(flag, value) {
            var flagNode = ui.getElement('editor-status.flags.' + flag);
            if (flagNode) {
                if (value) {
                    flagNode.style.backgroundColor = 'green';
                } else {
                    flagNode.style.backgroundColor = 'white';
                }
            }
        }

        function loadUpdateEditor(controller) {
            return new Promise(function(resolve, reject) {
                require(['./update'], function(Widget) {
                    // TODO: widget should make own bus.
                    var bus = runtime.bus().makeChannelBus({ description: 'Parent comm bus for input widget' }),
                        widget = Widget.make({
                            bus: bus,
                            workspaceInfo: workspaceInfo,
                            appId: env.appId,
                            appTag: env.appTag,
                            initialValue: model.getItem('params')
                        });
                    controller.widget = widget;
                    controller.desc = 'update editor widget';
                    widgets.editor = {
                        path: ['editor', 'widget'],
                        // module: widgetModule,
                        type: 'update',
                        bus: bus,
                        instance: widget
                    };

                    bus.on('parameter-sync', function(message) {
                        var value = model.getItem(['params', message.parameter, 'value']);
                        bus.send({
                            parameter: message.parameter,
                            value: value
                        }, {
                            // This points the update back to a listener on this key
                            key: {
                                type: 'update',
                                parameter: message.parameter
                            }
                        });
                    });

                    bus.on('sync-params', function(message) {
                        message.parameters.forEach(function(paramId) {
                            bus.send({
                                parameter: paramId,
                                value: model.getItem(['params', message.parameter, 'value'])
                            }, {
                                key: {
                                    type: 'parameter-value',
                                    parameter: paramId
                                },
                                channel: message.replyToChannel
                            });
                        });
                    });

                    bus.respond({
                        key: {
                            type: 'get-parameter'
                        },
                        handle: function(message) {
                            return {
                                value: model.getItem(['params', message.parameterName, 'value'])
                            };
                        }
                    });

                    bus.on('parameter-changed', function(message) {
                        model.setItem(['params', message.parameter], message.newValue);
                        evaluateAppState();
                    });

                    bus.on('parameter-touched', function(message) {
                        // model.setItem(['params', message.parameter, 'touched'], true);
                        var state = fsm.getCurrentState(),
                            newState = JSON.parse(JSON.stringify(state.state));
                        newState.data = 'touched';
                        fsm.newState(newState);
                        evaluateAppState();
                    });

                    return widget.start({
                            node: controller.node,
                            appSpec: env.appSpec,
                            parameters: spec.getSpec()
                        })
                        .then(function() {
                            resolve();
                            return null;
                        })
                        .catch(function(err) {
                            console.error('ERROR starting editor widget', err);
                            reject(err);
                        });
                }, function(err) {
                    console.error('ERROR', err);
                    reject(err);
                });
            });
        }

        function doShowMessage(message) {
            var messageWidget = MessageWidget.make();
            widgets.editor.instance = messageWidget;
            return messageWidget.start({
                content: message,
                node: ui.getElement('editor.widget')
            });
        }

        function renderCurrentlyEditing() {
            var info = editorState.getItem('current.set.info');
            var content = table({ class: 'table table-striped' }, [
                tr([th('Name'), td({ style: { fontWeight: 'bold' } }, info.name)]),
                tr([th('Ref'), td(info.ref)]),
                tr([th('Last saved'), td(info.saveDate.toLocaleDateString() + ' at ' + info.saveDate.toLocaleTimeString())]),
                tr([th('By'), td(info.saved_by)])
            ]);

            ui.setContent('currently-editing.widget', content);
            ui.setContent('currently-editing.name', info.name);
        }

        /*
         * Given an object ref, fetch the set object via the setApi,
         * then populate
         */
        function loadData(objectRef) {
            // TODO: check if the editor has unsaved changed, and
            // show an error message if so, and refuse to switch.
            var setApiClient = new GenericClient({
                    url: runtime.config('services.service_wizard.url'),
                    token: runtime.authToken(),
                    module: 'SetAPI',
                    version: 'dev'
                }),
                params = {
                    ref: objectRef,
                    include_item_info: 1
                };

            return setApiClient.callFunc('get_reads_set_v1', [params])
                .spread(function(setObject) {
                    // After getting the reads set object, we populate our
                    // view model (data model-ish) with the results.
                    // The editor will sync up with the model, and pick up the
                    // values.
                    model.setItem('params', {});

                    // TODO: move this into code or config specific to
                    // the reads set editor.
                    // *** removed the .value
                    model.setItem('params.name', setObject.info[1]);
                    model.setItem('params.description', setObject.data.description);
                    model.setItem('params.items', setObject.data.items.map(function(item) {
                        return {
                            ref: item.ref,
                            label: item.label
                        };
                    }));

                    var objectInfo = serviceUtils.objectInfoToObject(setObject.info);

                    // Might as well set here.
                    editorState.setItem('current.set.ref', objectInfo.ref);
                    editorState.setItem('current.set.info', objectInfo);

                    // NOT USED?
                    model.setItem('currentReadsSet', objectInfo);

                    // return loadUpdateEditor();
                });
        }

        /*
         * Reset the editor to default values for the parameters.
         * TODO: this really should be done through the spec, but we
         * are rapidly cutting corners here...
         */
        function resetEditorModel(objectRef) {
            model.setItem('params', {});
            model.setItem('params.name', '');
            model.setItem('params.description', '');
            model.setItem('params.items', []);
        }

        function doCreateNewSet(name) {
            var setApiClient = new GenericClient({
                    url: runtime.config('services.service_wizard.url'),
                    token: runtime.authToken(),
                    module: 'SetAPI',
                    version: 'dev'
                }),
                params = {
                    workspace: String(workspaceInfo.id),
                    output_object_name: name,
                    data: {
                        description: '',
                        // set api has bug -- will throw exception if fetch a
                        // set with no items.
                        // stuff a sample item in here to start with.
                        items: []
                    }
                };
            return setApiClient.callFunc('save_reads_set_v1', [params])
                .spread(function(result) {
                    doEditObject(serviceUtils.objectInfoToObject(result.set_info));

                    // return unloadEditor()
                    //     .then(function() {
                    //         var loading = loadingWidget.make();
                    //         return loading.start({
                    //                 node: ui.getElement('editor.widget'),
                    //                 message: 'Loading Reads Set'
                    //             })
                    //             .then(function() {
                    //                 return loadData(result.set_ref);
                    //             })
                    //             .then(function() {
                    //                 return loading.stop();
                    //             })
                    //     })
                    //     .then(function() {
                    //         return loadUpdateEditor();
                    //     })
                    //     .then(function() {
                    //         renderCurrentlyEditing();
                    //         ui.collapsePanel('edit-object-selector');
                    //         evaluateAppState(true);
                    //     });
                })
                .catch(function(err) {
                    console.error('ERROR getting reads set ', err);
                    console.error(err.detail ? err.detail.replace('\n', '<br>') : '');
                    loadErrorWidget(err);
                });

        }

        function doSaveReadsSet() {
            return Promise.try(function() {
                cell.execute();
                var state = JSON.parse(JSON.stringify(fsm.getCurrentState().state));
                state.data = 'clean';
                fsm.newState(state);
            });
        }

        var editorControllers = {};

        function unloadEditorController(controller) {
            var originalStatus = controller.status;
            controller.status = 'unloading';
            controller.cancelled = true;
            return Promise.try(function() {
                    // stop the widget if there is one.
                    if (controller.widget) {
                        controller.status = 'stopping';
                        return controller.widget.stop()
                            .then(function() {
                                controller.status = 'stopped';
                                controller.widget = null;
                            });
                    }
                })
                .then(function() {
                    var editorNode = ui.getElement('editor.widget');
                    try {
                        editorNode.removeChild(controller.node);
                    } catch (ex) {
                        console.warn('Error removing widget controller node', ex);
                    }
                });
        }

        function unloadEditors() {
            return Promise.all(Object.keys(editorControllers).map(function(id) {
                var controller = editorControllers[id];
                return unloadEditorController(controller)
                    .then(function() {
                        delete editorControllers[id];
                    });
            }));
        }

        // Widget controller

        function unloadWidgetController(controller) {
            var originalStatus = controller.status;
            controller.status = 'unloading';
            controller.cancelled = true;
            return Promise.try(function() {
                    // stop the widget if there is one.
                    if (controller.widget) {
                        controller.status = 'stopping';
                        return controller.widget.stop()
                            .then(function() {
                                controller.status = 'stopped';
                                controller.widget = null;
                            });
                    }
                })
                .then(function() {
                    var editorNode = ui.getElement('editor.widget');
                    try {
                        editorNode.removeChild(controller.node);
                    } catch (ex) {
                        console.warn('Error removing widget controller node', ex);
                    }
                });
        }

        function unloadWidgets() {
            return Promise.all(Object.keys(editorControllers).map(function(id) {
                var controller = editorControllers[id];
                return unloadWidgetController(controller)
                    .then(function() {
                        delete editorControllers[id];
                    });
            }));
        }

        function doShowWidget(widgetFactory, arg) {
            // New, create control object.
            var controller = {
                id: new Uuid(4).format(),
                node: document.createElement('div'),
                widget: null,
                cancelled: false,
                status: 'creating'
            };

            arg.node = controller.node;

            return unloadWidgets()
                .then(function() {
                    editorControllers[controller.id] = controller;
                    controller.widget = widgetFactory.make();
                    controller.desc = '?? widget ??';
                    controller.status = 'starting';
                    ui.getElement('editor.widget').appendChild(controller.node);
                    return controller.widget.start(arg);
                })
                .catch(CancellationError, function(err) {
                    console.warn('editor loading was cancelled', err);
                })
                .catch(function(err) {
                    alert('internal error: ' + err.message);
                });
        }

        function doEditObject(objectInfo) {
            // New, create control object.
            var controller = {
                id: new Uuid(4).format(),
                node: document.createElement('div'),
                widget: null,
                cancelled: false,
                status: 'creating'
            };

            // Update editor state (is also persistent in the metadata)
            editorState.setItem('current.set.ref', objectInfo.ref);
            editorState.setItem('current.set.info', objectInfo);

            return unloadEditors()
                .then(function() {
                    editorControllers[controller.id] = controller;
                    controller.widget = loadingWidget.make();
                    controller.desc = 'loading widget.';
                    controller.status = 'starting';
                    ui.getElement('editor.widget').appendChild(controller.node);
                    return controller.widget.start({
                        node: controller.node,
                        message: 'Loading Reads Set'
                    })
                })
                .then(function() {
                    if (controller.cancelled) {
                        throw new CancellationError();
                    }
                    return loadData(objectInfo.ref);
                })
                .then(function() {
                    if (controller.cancelled) {
                        throw new CancellationError();
                    }
                    return controller.widget.stop();
                })
                .then(function() {
                    if (controller.cancelled) {
                        throw new CancellationError();
                    }
                    return loadUpdateEditor(controller);
                })
                .then(function() {
                    if (controller.cancelled) {
                        throw new CancellationError();
                    }
                    renderCurrentlyEditing();
                    ui.collapsePanel('edit-object-selector');
                    evaluateAppState(true);
                })
                .catch(CancellationError, function(err) {
                    console.warn('editor loading was cancelled', err);
                })
                .catch(function(err) {
                    alert('internal error: ' + err.message);
                });
        }

        function loadEditObjectSelector() {
            return new Promise(function(resolve, reject) {
                require([
                    './selector'
                ], function(Widget) {
                    var widget = Widget.make({
                        workspaceInfo: workspaceInfo,
                        objectType: 'KBaseSets.ReadsSet'
                    });
                    widgets.editObjectSelector = {
                        path: ['edit-object-selector', 'widget'],
                        instance: widget
                    };
                    // When the user selects a reads set to edit.
                    widget.channel.on('changed', function(message) {
                        // Call this when we have a new object to edit. It will
                        // take care of updating the cell state as well as
                        // rendering the object.
                        //editorState.setItem('current.set.ref', objectInfo.ref);
                        //editorState.setItem('current.set.info', objectInfo);
                        var currentObject = editorState.getItem('current.set.info');
                        var newObject = message.objectInfo;
                        if (!newObject) {
                            if (currentObject) {
                                return doShowWidget(MessageWidget, {
                                    content: div({
                                        style: {
                                            textAlign: 'center'
                                        }
                                    }, 'No reads set selected. Please use the "Select Object to Edit" section above to create or edit a Reads Set.')
                                });
                            } else {
                                // do nothing, no editor displaying.
                            }
                        } else {
                            if (currentObject) {
                                if (currentObject.ref !== newObject.ref) {
                                    // replace it
                                    doEditObject(message.objectInfo);
                                } else {
                                    // do nothing, just leave editor alone.
                                }
                            } else {
                                // loadit for the first time, same thing.
                                doEditObject(message.objectInfo);
                            }
                        }
                    });
                    widget.channel.on('create-new-set', function(message) {
                        doCreateNewSet(message.name);
                    });
                    widget.channel.on('fatal-error', function(message) {
                        setFatalError({
                            title: 'Fatal error from ' + message.location,
                            message: message.error.message,
                            details: message.error.details || 'You may need to consult the browser log for additional information',
                            advice: message.error.advice
                        });
                        renderUI();
                    });
                    widget.start({
                            node: ui.getElement(['edit-object-selector', 'widget']),
                            appSpec: env.appSpec,
                            selectedSet: editorState.getItem('current.set.ref')
                        })
                        .then(function() {
                            resolve();
                            return null;
                        })
                        .catch(function(err) {
                            reject(err);
                        });
                }, function(err) {
                    console.error('ERROR', err);
                    reject(err);
                });
            });
        }

        function gatherValidationMessages(validationResult) {
            var messages = [];

            function harvestErrors(validations) {
                if (validations instanceof Array) {
                    validations.forEach(function(result, index) {
                        if (!result.isValid) {
                            messages.push(String(index) + ':' + result.errorMessage);
                        }
                        if (result.validations) {
                            harvestErrors(result.validations);
                        }
                    });
                } else {
                    Object.keys(validations).forEach(function(id) {
                        var result = validations[id];
                        if (!result.isValid) {
                            messages.push(id + ':' + result.errorMessage);
                        }
                        if (result.validations) {
                            harvestErrors(result.validations);
                        }
                    });
                }
            }
            harvestErrors(validationResult);
            return messages;
        }

        function evaluateAppState() {
            return Promise.try(function() {
                    var currentEditorSetInfo = editorState.getItem('current.set.info');

                    if (!currentEditorSetInfo) {
                        // nothing being edited.
                        fsm.updateState({
                            mode: 'new'
                        });
                        return null;
                    }

                    return validateModel()
                        .then(function(result) {
                            // we have a tree of validations, so we need to walk the tree to see if anything
                            // does not validate.
                            var messages = gatherValidationMessages(result);

                            if (messages.length === 0) {
                                buildPython();
                                // fsm.updateState({ params: 'complete' });
                                // dumb, but gotta get it working...
                                fsm.newState({
                                    mode: 'editing',
                                    params: 'complete',
                                    data: 'changed'
                                });
                            } else {
                                resetPython(cell);
                                // fsm.newState({ mode: 'editing', params: 'incomplete', data: 'changed' });
                                //fsm.updateState({ params: 'incomplete' });
                                fsm.newState({
                                    mode: 'editing',
                                    params: 'incomplete',
                                    data: 'changed'
                                });
                            }
                        });

                })
                .then(function() {
                    renderUI();
                })
                .catch(function(err) {
                    alert('internal error'),
                        console.error('INTERNAL ERROR', err);
                });
        }

        function setFatalError(arg) {
            editorState.setItem('fatalError', {
                title: arg.title,
                message: arg.message,
                details: arg.details,
                advice: arg.advice
            });
            syncFatalError();
            fsm.newState({ mode: 'fatal-error' });
        }

        // LIFECYCLE

        function registerEvents() {
            bus.on('toggle-code-view', function() {
                var showing = toggleCodeInputArea(),
                    label = showing ? 'Hide Code' : 'Show Code';
                ui.setButtonLabel('toggle-code-view', label);
            });
            bus.on('show-notifications', function() {
                doShowNotifications();
            });
            bus.on('save', function() {
                doSave();
            });
            //                bus.on('remove', function () {
            //                    doRemove();
            //                });

            bus.on('on-success', function() {
                doOnSuccess();
            });

            // Events from widgets...

            parentBus.on('newstate', function(message) {
                console.log('GOT NEWSTATE', message);
            });

            parentBus.on('reset-to-defaults', function() {
                bus.emit('reset-to-defaults');
            });

            cellBus = runtime.bus().makeChannelBus({
                name: {
                    cell: Props.getDataItem(cell.metadata, 'kbase.attributes.id')
                },
                description: 'A cell channel'
            });

            eventManager.add(cellBus.on('delete-cell', function() {
                doDeleteCell();
            }));

            eventManager.add(cellBus.on('result', function(message) {
                // Verify that the run id is the same.
                if (message.address.run_id !== editorState.getItem('editorState.currentRunId')) {
                    setStatus(div([
                        p('Error! result message is not from the generated code!'),
                        p(['Sent ', editorState.getItem('editorState.currentRunId'), ' received ', message.address.run_id])
                    ]));
                    return;
                }
                if (message.message.result) {
                    setStatus('Successfully saved the reads set');
                    editorState.setItem('editorState.touched', false);
                    editorState.setItem('editorState.changed', false);
                    fsm.newState({
                        mode: 'editing',
                        params: 'complete',
                        data: 'clean'
                    });
                    renderUI();

                    // Now we need to reload the editor with the NEW item.
                    editorState.setItem('current.set.ref', message.message.result.set_ref);
                    var objectInfo = serviceUtils.objectInfoToObject(message.message.result.set_info);
                    editorState.setItem('current.set.info', objectInfo);
                    JupyterProxy.saveNotebook();
                    // ui.setContent('editor.widget', html.loading('Loading saved Reads Set'));

                    return doEditObject(objectInfo);
                } else if (message.message.error) {
                    // cheap as heck error message
                    var errorMessage = div({ class: 'alert alert-danger' }, [
                        'Error saving reads set: ',
                        message.message.error.message
                    ]);
                    setStatus(errorMessage);
                } else {
                    setStatus('what?');
                }
            }));
        }

        function loadSpec() {
            return new Promise(function(resolve) {
                require(['./spec'], function(editorSpec) {
                    var spec = Spec.make({
                        spec: editorSpec
                    });
                    resolve(spec);
                });
            });
        }

        function start(arg) {

            // Set up the top level DOM node and build the layout.
            hostNode = arg.node;
            container = hostNode.appendChild(document.createElement('div'));
            ui = Ui.make({
                node: container,
                bus: bus
            });

            var events = Events.make({
                node: container
            });
            container.innerHTML = buildLayout(events);
            events.attachEvents();

            initializeFSM();
            initCodeInputArea();

            return loadSpec()
                .then(function(loadedSpec) {
                    spec = loadedSpec;
                    registerEvents();
                    showCodeInputArea();
                    return syncAppSpec(arg.appId, arg.appTag)
                })
                .then(function() {
                    // Should not need to do this each time...
                    var appRef = [editorState.getItem('app').id, editorState.getItem('app').tag].filter(toBoolean).join('/');
                    var url = '/#appcatalog/app/' + appRef;
                    utils.setCellMeta(cell, 'kbase.attributes.title', env.appSpec.info.name);
                    utils.setCellMeta(cell, 'kbase.attributes.subtitle', env.appSpec.info.subtitle);
                    utils.setCellMeta(cell, 'kbase.attributes.info.url', url);
                    utils.setCellMeta(cell, 'kbase.attributes.info.label', 'more...');

                    return loadEditObjectSelector();
                })
                .then(function() {
                    // only load the editor up if we have an existing set.
                    // NEW: get the most recent one, not just the most recently selected one.
                    if (editorState.getItem('current.set.info')) {
                        console.log('START() -- LOADING OBJECT IN editor');
                        return doEditObject(editorState.getItem('current.set.info'));
                    } else {
                        return doShowWidget(MessageWidget, {
                            content: div({
                                style: {
                                    textAlign: 'center'
                                }
                            }, 'No reads set selected. Please use the "Select Object to Edit" section above to create or edit a Reads Set.')
                        });
                    }
                })
                .then(function() {
                    // this will not change, so we can just render it here.
                    PR.prettyPrint(null, container);
                })
                .then(function() {
                    // if we start out in 'new' state, then we need to promote to
                    // editing...
                    if (fsm.getCurrentState().state.mode === 'new') {
                        // fsm.newState({mode: 'editing', params: 'incomplete'});
                        evaluateAppState();
                    }
                    renderUI();
                })
                .catch(function(err) {
                    console.error('ERROR loading main widgets', err);
                    addNotification('Error loading main widgets: ' + err.message);
                    setFatalError({
                        title: 'Error loading main widgets',
                        message: err.message,
                        details: err.details,
                        advice: err.advice
                    });
                    renderUI();
                });
        }

        function stop() {
            return Promise.try(function() {
                return Promise.all(Object.keys(widgets).map(function(key) {
                    return widgets[key].stop();
                }));
                // busConnection.top();
            });
        }

        // INIT

        model = Props.make({
            data: {},
            onUpdate: function(props) {
                renderUI();
            }
        });

        editorState = Props.make({
            data: utils.getCellMeta(cell, 'kbase.editorCell'),
            onUpdate: function(props) {
                utils.setCellMeta(cell, 'kbase.editorCell', props.getRawObject());
                renderUI();
            }
        });

        return {
            start: start,
            stop: stop
        };
    }

    return {
        make: function(config) {
            return factory(config);
        }
    };
}, function(err) {
    console.error('ERROR loading editorCell editorCellWidget', err);
});


text:
Jude P. Morte
Retro Thang
Jude P. Morte September 18, 2006 00:00
Make:Chrysler
Model:300C 3.5L V6
Engine:3.5-liter 24-valve V6
Max Power:[email protected]
Max Torque:250 [email protected],800rpm
Transmission:5-speed A/T
Price as Tested:₱
FIND MORE REVIEWS
Choose BrandAston MartinAudiBAICBMWBYDChanaCheryChevroletChryslerDodgeFerrariFordFotonGACGeelyHondaHyundaiIsuzuJACJaguarJeepJMCKiaLand RoverLexusMahindraMaseratiMaxusMazdaMercedes-BenzMGMINIMitsubishiNissanPeugeotPorscheRange RoverRAV4Rolls-RoyceSsangyongSubaruSuzukiTataToyotaVolkswagenVolvo -- Model --
2015 Chrysler 300C update makes PH debut
CATS Motors Brings in Limited Chrysler 300C Startech Edition
2010 Chrysler 300C CRD
NAIAS 2014: Introducing the All-new 2015 Chrysler 200 Sedan
Getaway, the Chrysler way
Chrysler LLC and Fiat Group Announce Global Strategic Alliance
Chrysler opens Makati dealership
Much of pop culture has always loved whatever was en vogue one or two generations ago, with obvious examples being remakes of old songs, movies and clothing styles. This makes you ask "Are they old or new?" But in many cases it's hard to tell new jack from old school, and it's even harder when the entity in question seamlessly blends old world charm with new world sophistication.
In the local auto arena, a perfect example would be the Chrysler 300C. US car history buffs will remember that in the 1950s, the release of the Chrysler C-300 (ancestor of the current 300C) boosted Chrysler vehicle sales by 17 percent. An eye-catching twin grille, chrome side strips on the car's flanks and 300 hp made the vehicle appealing to customers, with its 1956-1964 successors (collectively known as the "300" letter series due to the fact that each year's model had a new letter of the alphabet as a suffix) providing robust sales. However, it was dropped by 1965 due to cost-cutting measures caused by a US-wide recession.
When Chrysler merged with Mercedes Benz in 1998, the latter insisted that vehicles sold under the Chrysler name must go back to its post-World War II roots - in essence, a return to rear wheel drive, copious power and unique styling. The Chrysler 300C was the first vehicle (since the merger) to show customers the benefits of the merger.
Luxury old and new
The 300C's interior, much like its first impression to onlookers, is a good blend of then and now. Slide behind the leather-trimmed steering wheel and you'll instantly notice that the gauges (which turn green when the headlights are turned on) have a distinctly vintage look. The large round dials tote metallic trim rings, white faces with black numbers and a font that convenes an old and classy image. Ditto for the analog clock between the middle climate control vents.
The center console cubbyhole is cavernous (almost the same in volume as the Nissan Murano's) and features a 12-volt power outlet in addition to the outlet found within the front ashtray located in front of the a/t shift column. There are lamps within the doors (so occupants will be guided as to where are they stepping in the dark), while the rear view mirror and driver's side mirror has an auto-dim feature that minimizes glare. The MP3-capable Boston Acoustics head unit and seven-speaker system (with subwoofer) replicates tones faithfully, but needs help in the treble and midrange department. However, the OE sound system of the 300C is the best this writer has listened to date. Play Nat King Cole's "When I Fall in Love" or Norah Jones in the 300C's head unit and you'll see why.
The leather seats are soft and the inside materials have both a high-quality look and feel. The silver center dashboard trim is eye-catching and - believe it or not - plastic, not real aluminum or any other metal. It's the most convincing substitute this writer has seen in any vehicle. In fact, the 300 probably offers more features than you would expect for its Php 2.65M price.
The airconditioning provides Arctic-cold blasts (even at the lowest setting) in all temperatures and atmospheric situations. The climate control knobs (a nod to the Mercedes Benz E-Class, its platform sibling) are simple and straightforward, with a large round dial for fan speed and another for air direction. Both temperature control knobs (for driver and passenger) are situated in the same area and are easy to use. The round knobs are trimmed with chrome rings, an upscale touch that contributes to the vintage flair of the car.
But it's not all perfect. The vanity mirrors are illuminated, but are positioned in such a way that the mirror flaps block forward vision. The front cupholders can hold canned drinks, but cannot hold one-liter bottles. The size of the door speakers make storage areas within the doors limited to small paraphernalia. The rear seats have more than ample room, but given the car's overall level of luxury, we found the rear seat to be lacking in any features that might extend the luxurious setting beyond the front seats. The Chrysler Pacifica was specifically designed to include the rear-seat passengers in the car's luxury trappings with a rear console, fan speed adjuster and rear-seat warmers controlled via rear mounted switches. By comparison, the rear seat of the 300C is very plain, offering no more than a fold-down armrest with cupholders and rear aircon vents behind the center console.
Exterior examination shows that the arched wheel wells, combined with 18-inch polished aluminum wheels, a distinctly Chrysler large chrome grille, chrome mirrors, chrome bezel Xenon headlights and monotone paint (bright silver metallic for the test unit) give the car a low slung stance that's menacing and attractive. The body has an almost custom look as it appears to have a chopped top and removed bumpers, with short front and rear overhangs reminiscent of old Bentleys or its C-300 progenitor. This makes the 300C so dope (cool) that it needs to be in rehab. In fact, the car invites stares from old and new alike, and even prompted a gaggle of UP (University of the Philippines) Diliman students to remark about the car (like "How much is it?", "Is that your car?" and " That's a nice car. Where did you get it?") while this writer was a guest lecturer at UP's College of Mass Communication one Monday afternoon.
Not just luxury
Backing up the 300C's panache is performance that is distinctly American. The test unit 300C featured here totes a 3.5L 24-valve SOHC (single overhead camshaft) engine, with 250hp and 250 lbs. ft. (foot pounds) of torque, mated to a five-speed a/t and rear-wheel drive. At the low rpm range, the 300C isn't so quick as to elicit a jaw-dropping "wow," but an aggressive gas pedal squeeze brought out one of those unintentional smiles from this writer and 300C occupants alike. There's no turbo jolt or high-revving variable valve timing to wring out, just a subtle rumble and an urgent thrust. The five-speed automatic transmission shifts smoothly and without drama, but tends to jerk ever-so-slightly when downshifting. And speaking of performance, this writer managed to hit 230 kph on the northbound part of the Skyway (before running out of road), yet got 9.5 kilometers per liter on three days of mixed driving.
The 300C features an electronic stability program (ESP) that helps maintain directional stability on uneven surface areas, and can easily be turned on or off via a button below the analog clock. With the ESP engaged, hard cornering produces moderate understeer and a stiff ride. On the other hand, turn off the ESP and the understeer (and the subsequent stiffness) is virtually gone, with great grip being provided by the Pirelli P7 225/60R18 tires. Could this be thanks to the German influence of its underpinnings? Perhaps, but no matter the origin, the results can't be argued. The car delivers decent handling, a supple ride and a quiet interior whether at speed or high rpm levels. Brakes are firm and offer excellent feedback, and when the ABS is engaged, it makes little noise.
One complaint about the overall driving dynamics of the car is its long hood. The driver feels well aware that this is a massive piece of hardware and parking lots (or even u-turn joints) should not be taken lightly. If you're used to blasting into mall parking lots and then swinging into a "compact" space with little room to spare, you'll have to rethink your parking philosophy. In addition, the car's short overhangs can make it hard to judge how close you are to another vehicle or, say, a parking garage support post. The good news is that a park assist rear sensor (mounted above the rear window, within sight of the rearview mirror) gives you visual and audio warnings whenever the car is in reverse. Also, the side mirrors move down five to six degrees longitudinally when the car is in reverse, helping ease parking or long backing situations.
The Chrysler 300C does what many product designers and marketers alike wish they could do with regularity � offer a product that effectively captures the heritage and hipness of the past while seamlessly integrating convenience, value, dopeness (coolness) and safety of today. As confirmed by the revival of Nike Air Force One basketball shoes, it's the addition of a little history that makes the new version that much better. Sort of like making a retro thing into a retro thang.
- Next Car Reviews
2006 Isuzu Crosswind Sportivo
Jude P. Morte 2006-09-18 00:00:00
Previous Car Reviews -
2005 Toyota Fortuner 3.0V
2005-07-11 00:00:00 Raymond D. Young

redpajama_set_name: RedPajamaCommonCrawl


text:
Future Space Programs: Hearings Before the Committee on Science and ...
Por United States. Congress. House. Committee on Science and Technology
A plan is presented for the entire national space effort throughout the next 35 years, beginning in 1969. The plan is comprehensive in scope, and sufficiently detailed for an early management decision for or against its adoption. Although it does not depend on the extension of present engineering knowledge, it does fully provide for such an extension. It calls for reorganizing NASA (The National Aeronautics and Space Administration) to be the National Space Academy, to occupy the existing installations of the Manned Spacecraft Center, near Houston. The procurement and assembly of rockets and spacecraft would be assigned to a new, semi-private, Spacecraft Corporation, to be made possible by an enabling act of Congre66. Rationalization of the plan, together with recovery of launch rockets from all flights, and standardization of trips and spacecraft, would provide a capability far in excess of any plan heretofore suggested, at an annual cost substantially less than that of NASA in 1969.
NASA in 1967 terminated all funding of both in-house and contract planning for manned planetary exploration. One is sadly reminded of Turkey in 1623. It was recorded in "The Travels", by Elviya Tchelebi, Vol. I, pp.607-611, that Hezarfin (Thousand-famed) Ahmet Tchelebi (The Celebrated) made eight successful, manned flights in an unpowered glider. His last flight, in the presence of Sultan Murat Han (Murat IV), in 1623, was from the Tower of Galata to Dogan Meydani, four miles away, across the Bosporus. The sultan rewarded Ahmet with a pouch of gold,
and said, "You are a man to be feared. Whatever you set your mind to do you accomplish. The presence here of someone like you is dangerous".
He promptly banished Ahmet to Algiers.
A little later in the reign of the same sultan, during festivities in honor of the birth of the sultan's daughter Pakize, a Hungarian named Lagari Hasan made the first successful manned flight in a rocket powered glider. The story is recorded in the same book, p.671. The glider was powered by seven rockets containing 154 pounds of gunpowder paste. In the presence of the sultan, at the shore of Saraylburnu (Palace Grounds), Hasan mounted the rocket, his helpers lit the cord fuses, and he rose skyward as long as the powder lasted, after which. he glided to a successful landing on the grounds of the Kiosk of Suleyman Pasha (General Suleyman). He received a hero's welcome by the populace, and was brought before the sultan, who gave him a pouch of gold, promoted him to an official position in the army, and sent him to the Crimea, where he died.
It is alleged that the United States cannot at this time afford any new starts in the manned exploration of the solar system. The allegation may well be true, and it may equally well be false. judgement is being made in ignorance. Those who make it do so without having ever seen a master plan for space exploration, for it is a fact that until now neither NASA nor anyone else in the United States has presented any such plan. It is the purpose of this paper to present a plan whereby an informed judgement can be made.
24-215 0 - 78 - 50
7 SUMMARY AND RECOMMENDATIONS
2.1-a MASS OF ROCKET REQUIRED TO LAUNCH A UNIT MASS
OF SPACE ROCKET INTO A NEAR-PARABOLIC ELLIPSE
AROUND THE EARTH
2.1-b A VERSATILE SPACE ROCKET-LAUNCH ROCKET CONFIGURATION
2.2-a THE REFERENCE SPACE ROCKET
2.2-b TANK ARRANGEMENT IN THE REFERENCE SPACE ROCKET
GROWTH CURVES
2.4-a
MASS TABULATION MUTUALLY ADJUSTED FOR MARS AND
VENUS SHIPS. ROUND TRIP TO VENUS
2.4-b
2.4-c
VENUS SHIPS. ROUND TRIP TO MARS
8-CYLINDER GILLESPIE ROCKET
2.4-d
2.4-e
SELECTED SAMPLE SHIP MASSES, MUTUALLY ADJUSTED
3.1.1 NOMINAL TRIPS TO VENUS THROUGH ONE SYNODIC CYCLE 3.1.2 NOMINAL TRIPS TO MARS
3.1.3 STOPOVER TRIP OPPORTUNITIES TO MARS
CFFOSITION OF 1978
ESTIMATED ANNUAL COST


A heatwave calls for cooling cocktails, breezy dresses and glowy, dewy complexions. There's something about the heat which unleashes our inner bronzed goddess, and no glowing goddess would be complete without a luxury illuminator in her makeup wardrobe. Sculpted, sun-kissed cheeks, subtle shimmers, flushed complexions can all be achieved with our favourite luxe glow givers.
Bronze and highlight duos don't come much more iconic than SOLEIL TAN DE CHANEL BRONZE UNIVERSEL and POUDRE LUMIÉRE HIGHLIGHTER. Both are radiant alone, but together, they're a force to be reckoned with. Simply wear SOLEIL TAN DE CHANEL BRONZE UNIVERSEL alone for a healthy, sun-kissed glow, or sweep it over your foundation for enhanced radiance. For a more sculpted, contoured look, apply the bronzer just beneath your cheekbones, starting from your ears and ending in the middle of your cheek using a back and forth motion. To extend the glow beyond your complexion: mix the bronzer with a small amount of your favourite CHANEL moisturiser. For a truly dazzling result, complete the look by applying POUDRE LUMIÉRE HIGHLIGHTER to the high points of your face, illuminating your cheekbones and igniting your natural beauty.
Swirl your brush around this multi-dimensional powder to score that stunning glowing-from-within look. Awaken bare skin or give a sculpted, finishing touch to a made up face with a blend of the flattering bronze, rosy coral blush and champagne highlight hues. Not only will this make your skin look elevated, but the formula is packed with ingredients that protect it against free radicals and pollution, making it the perfect product for bringing your bronze to the beach right through to the city.
What's better than one dewy, illuminating highlighter? A duo of stunning highlighters. This luxurious white compact holds a velvety rose gold hued highlight, along with a glistening gold illuminator, a dream for any highlighter fiend. The versatile product grants you the ability to use the individual shades alone, or blend together to create a unique shade of shimmer to wear on the high points of your face, decolletage or swept across your eyelids for a sheer glossy, bronzed summer eye look.
Hello, gorgeous summer trio. Take your pick of the golden bronze, deep tan or pink toned blush and apply them alone to tailor a bronzed, flushed look which is as unique as you are. Alternatively, for a hue which guarantees to effortlessly lift and energise your base, mix all three shades together with a larger blending brush. These buttery powders blend seamlessly onto skin, meaning hasty, on-the-run touch ups are effortless and worry free. No need to fuss over blending, more time to think about your next summer day trip.


text:
Commentary: With vaccine stance, Nurses Association sets poor example
New York facing state government workforce crisis
Emily A. Largent and Dominic Sisti
The New York State Nurses Association — a labor union representing over 40,000 nurses — recently issued a position statement that begins by emphasizing NYSNA's support for "the recommendation that everyone be vaccinated against SARS-CoV-2, the coronavirus that causes COVID-19 in a just, fair, and equitable manner." Given stagnating COVID-19 vaccination rates and surging cases, we were heartened to hear nurses, consistently rated amongst the most honest and ethical professionals, affirming the importance of vaccines.
But as we read on, our view of the position statement soured: "NYSNA strongly opposes the mandatory vaccination of health care providers for COVID-19 as a condition of employment or as a state or federal mandate."
States can mandate vaccination to protect public health and promote the safety of their citizens, and employers can require employees to be vaccinated so long as they provide reasonable accommodations. This is likely true — despite what NYSNA suggests — even for vaccines available only under an emergency use authorization. A number of hospitals and health systems have in fact already required that employees and clinical staff be vaccinated against COVID-19. In June, a federal district court judge dismissed a lawsuit brought against Houston Methodist, one of the nation's first health systems to mandate COVID-19 vaccines, writing that the mandate "is a choice made to keep staff, patients, and their families safer." We note, however, that when part of an employer's workforce is represented by a union, additional legal considerations can include the need to satisfy bargaining obligations before implementing a mandate.
Not only are vaccine mandates generally legal, they are ethical and justified when, as with COVID-19, they protect against an illness that constitutes a significant threat to health and wellbeing. Yet NYSNA twists familiar ethical concepts — do no harm, justice, beneficence, autonomy, informed consent — to suggest that vaccine mandates for health care workers remain ethically controversial. This is wrong. The nursing code of ethics states that a "nurse's primary commitment is to the patient, whether an individual, family group, community, or population." Patients, some of whom cannot yet be immunized and some for whom vaccines are not protective, have a strong interest in not getting COVID-19 from those caring for them and also in having a healthy workforce available to them. This is a powerful moral reason for treating vaccination of all health care workers, including nurses, as a professional duty. And it is why more than 60 medical groups, including the American Nurses Association, issued a joint statement saying it is ethically imperative for all health care and long-term care employers to require COVID-19 vaccination.
Nurses have been critical to the functioning of our health care system throughout the pandemic and are intimately familiar with the impact of COVID-19. Given all this, why would NYSNA oppose mandatory COVID-19 vaccination for health care providers? It appears NYSNA is using vaccine refusal to advance its bargaining power; nurse and NYSNA executive director Pat Kane said as much in a recent interview.
What can we say about NYSNA's apparent willingness to put patients and the public health at risk to improve their position at the bargaining table? They are forgetting and forsaking their more fundamental ethical obligations.
COVID-19 misinformation has unnecessarily killed too many people. The vaccines are safe and effective, with nearly 4 billion doses administered worldwide. Ambivalent messaging about COVID-19 vaccines from the leadership of NYSNA and other influential health care unions coupled with a rejection of their professional duty to be vaccinated is a poor example for members and for the public.
Bioethics is often complicated. This is not. Front-line health care workers should be vaccinated against COVID-19.
Sign up for the Observation Deck newsletter
Read the latest Times Union opinion, perspective and letters to the editor on Mondays by signing up for our Observation Deck newsletter.


This die struck classic solitaire engagement ring is timeless with its simple clean lines. When ordered in pink gold it gives the color a chance to shine and take center stage. Just remember to order the setting in white gold or platinum, otherwise the blush hue can reflect in the stone and mask the clean color of your diamond.
Floral engagement ring settings are also a popular choice and pair beautifully with the feminine quality of pink gold. The ring below features beautiful flowers in relief as well as leaf and organic decorative details. This ring is like a bouquet that will never wilt away; just like your love for her.
This is the perfect ring for any bride-to-be that loves clean but still wants a touch of something unique. The engraved side details on are as beautiful as they are understated.
Is your bride-to-be looking for a modern diamond setting? If yes, then this is the setting for her. The tapered channel set diamonds draw your eye to the center stone, keeping the focus on the main diamond while adding the perfect amount of sparkle to the shank.
If you are looking for a unique engagement ring then check out this amazing vintage made die struck ring. A couple cool facts about this ring, first, its dies struck! Second, this ring is made using a vintage die that has been around since the early years at Jabel; it is literally a 'new' 'vintage' ring and the pink gold ties in perfect with its antique history. Third, the triquetra pattern on the shoulders is a celebrated symbol that has been adopted by many cultures and faiths throughout history. Finally, the full bezel setting will add extra protection for your diamond and makes this an excellent setting for an active bride. So, if you're bride-to-be wants to stand out from the crowd, this is the ring for her.


text:
#ifndef TRIGGER_SYSTEM_HPP
#define TRIGGER_SYSTEM_HPP

#include <list>

namespace agent
{
  namespace trigger
  {
    template<class Trigger_t>
    class System
    {
    public:

      typedef std::list<Trigger_t*> TriggerList;

    private:

      TriggerList m_Triggers;

      // This method iterates through all the triggers present in the system
      // and calls their update method in order that their internal state
      // can be updated if necessary. It also removes any triggers from
      // the system that have their m_isRemovedFromGame field set to true.
      void UpdateAllTriggers()
      {
	typename TriggerList::iterator curr = m_Triggers.begin();
	while(curr != m_Triggers.end()) {
	  if( (*curr)->IsToBeRemoved() ) {
	    delete *curr;
	    curr = m_Triggers.erase(curr);
	  }
	  else {
	    (*curr)->Update();

	    curr ++;
	  }
	}
      }

      // This method iterates through the container of entities passed
      // as a parameter and passes each one to the doTry method of each trigger
      // *provided* the entity is alive and provided the entity is ready
      // for a trigger update.
      template<class Container>
      void TryTriggers(Container& entities)
      {
	// test each entity against the triggers
	typename Container::iterator currEnt = entities.begin();
	for(currEnt; currEnt != entities.end(); currEnt++) {
	  if( (*currEnt)->IsReadyForTriggerUpdate() && (*currEnt)->IsAlive() ) {
	    typename TriggerList::const_iterator currTrg = m_Triggers.begin();
	    for(currTrg; currTrg != m_Triggers.end(); currTrg++) {
	      (*currTrg)->Try(*currEnt);
	    }
	  }
	}
      }

    public:

      ~System() { Clear(); }

      // This deletes any current triggers and empties the trigger list.
      void Clear()
      {
	typename TriggerList::iterator currTrg = m_Triggers.begin();
	for(currTrg; currTrg != m_Triggers.end(); currTrg++) {
	  delete *currTrg;
	}

	m_Triggers.clear();
      }

      // This method should be called each update-step of the game.
      // It will first update the internal state of the triggers
      // and then try each entity against each active trigger to test
      // if any should be triggered.
      template<class Container>
      void Update(Container& entities)
      {
	UpdateAllTriggers();
	TryTriggers(entities);
      }

      // This is used to register triggers with the System
      // (the System will take care of tidying up memory used by a trigger)
      void Register(Trigger_t* trigger)
      {
	m_Triggers.push_back(trigger);
      }

      /*
      // Some triggers are requred to be rendered
      // (like giver-triggers for example)
      void render()
      {
	TriggerList::iterator currTrg = m_Triggers.begin();
	for(currTrg; currTrg != m_Triggers.end(); currTrg ++) {
	  (*currTrg)->render();
	}
      }
      */

      const TriggerList& GetTriggers() const { return m_Triggers; }

    };
  } // namespace trigger
} // namespace agent

#endif

redpajama_set_name: RedPajamaGithub


My Watermelon Moon: Oh Gingerbread!
I have a little obsession with gingerbread houses. It started when I was young with an awesome dollhouse that my grandparents built for us. It was wired and had wall to wall carpet, working doors, it was amazing.
Honestly, as an adult I might still have dollhouses around to decorate and make stuff for, but they take up a lot of room, even if they are supposed to be "small" they aren't. LOL. Anyhow, I have a thing for architecture and houses and well you get the picture.
Then at some point I decided that gingerbread was the way to have the best of both worlds. They are cute, smell great, and they go away after awhile.
That's it for today... The holiday's are hitting home with lots of activities this weekend! How did we suddenly get to December???
these are soo cute, I know it is not exactly a recipe but love for you to share this holiday post on friday food frenzy if you have a chance.
Everything is adorable! and fun!
HIMCR Glitz & Glam Blog Hop and Challenge!


10 best above ground pools 2018 best backyard gear. Inground pool prices installed garden design with best. Best backyard swimming pools for kids reviews. Beautiful swimming pool picture of royalton hicacos. Backyard landscaping ideas swimming pool design read more. Best backyard swimming pools for kids reviews. Small backyard inground wading pools joy studio design.
Timber deck design ideas get inspired by photos of. Landscaping ideas for small backyards townhouses townhouse. Unique wedding ideas in winter concepts best wedding. Kidney shaped pool on pinterest pool shapes, swimming. Room set up diagrams room set up examples ~ elsavadorla. Descanso gardens ~ enchanted: forest of light sirens. Outdoor lighting to brighten your terrace, patio, or porch. Best solar garden lights 17 best 1000 ideas about solar. Best narrow backyard ideas ideas on pinterest. 25 best ideas about backyard splash pad on pinterest. Indoor herb garden ideas 14 diy herb garden ideas for.
De 25 bedste ider inden for four o clock p pinterest. Gorgeous backyard garden in full bloom hometalk. Backyard flower bed designs. Backyard flower gardens your neighbors will envy. 10 small flower garden ideas to build a serene backyard. 13 best front yard ideas images on pinterest backyard. Backyard flower garden layout exterior design ideas.


text:
Cyber surfing: Saturday
Good morning. Here's what's "out there" about the Seahawks for today, Nov. 5:
Danny O'Neil at the Seattle Times looks at Mike Williams, who is expected to return to the lineup at split end in Sunday's game against the Cowboys after sitting out last week. Offers O'Neil: "Seattle signed Sidney Rice as a free agent with the belief he could be the team's No. 1 receiving option. He has finished with more than 100 yards receiving in two of the five games he has played. Williams – who has missed two of the past three games because of injuries – was supposed to be the other side of that equation. He has nine catches in the five games he has played at a position with as much competition as any on the roster. Ben Obomanu started in Williams' place last week, and he caught four passes for 107 yards."
Eric Williams of the News Tribune catches up with Jon Kitna, the former Seahawks, Central Washington University and Lincoln High School QB, who is the backup to Tony Romo in Dallas and in his 15th NFL season. Says Williams, and Kitna: "Kitna's in the final year of his contract with the Cowboys and doesn't know what his plans are beyond this season. 'The way I'm looking at it is, whenever I'm done here and my contract is up we'll see what the Lord has in store with me and my family,' Kitna said. 'We're good either way. If God presents us with another opportunity, we're good with it. But we're excited about the next phase of our life, too.' Kitna's wife, Jennifer, and the rest of family stayed locally in a home the family finished building in the Lakewood area in January. It's the first time in his 15-year career that he's lived apart from his family during the season, although they still see each other every couple of weeks."
Mike Sando at ESPN.com has the "Final Word" on the NFC West heading into Week 9, including this nugget of an item on Marshawn Lynch: "Getting the ground game going stands as a top priority for the Seahawks over the final nine games of the season. The team expects to have its projected offensive line starting for the second week in a row after not playing together since Week 1. Marshawn Lynch hasn't found much running room, but he does have a rushing touchdown in three consecutive games. He's looking to become the first Seattle runner since Shaun Alexander in 2005 to score one in four consecutive games. The Cowboys allowed 239 yards rushing to Philadelphia last week after entering the game allowing a league-low 69.7 yards per game."
Here at Seahawks.com, we take a look at the phenomenon that is "Friday Night Lights" through the Seahawks who played their high school football in Texas. Says middle linebacker David Hawthorne: " 'Friday Night Lights' is real out there. We think we play football better than anybody else.' "
We've also got a look at Friday's practice in words and video, including the latest on QB Tarvaris Jackson's status for the game.
For a look at the rest of the league, there's Clark Judge's "Peek at the Week" at CBSSports.com; John Clayton's "First and 10" at ESPN.com; and Peter King's "Game Plan" at SI.com.
November 5, 2011 – 9:37 am
Tags: Cyber surfing, David Hawthorne, Jon Kitna, Marshawn Lynch, Mike Williams, Tarvaris Jackson
Comments Off on Cyber surfing: Saturday


text:
Abu-l-Fat·h Muhàmmad ibn Annaz fou el fundador de la dinastia annàzida. Era un cap kurd; els seus títols eren hàjib i nadjib pel que cal suposar que era un funcionari del buwàyhida Baha al-Dawla (980-1013) i va poder governar a Hulwan del 991 al 1010.

El 997 es va apoderar de Dakuka que pertanyia als Banu Uqayl. El 999 va aniquilar el petit feu local de Zahman ibn Hindi a Khanikin. El 1002 va lluitar contra el Banu Mazyad (mazyàdides) aliat al cap Hadjdjadj ibn Hormuz. El mateix any es va posar al servei de Amid al-Djuyush.

El 1006 fou expulsat de Hulwan pel kurd Badr ibn Hasanwayh aliat a Abu l-Hasan Ali ibn Mazyad, i es va retirar a Bagdad amb el visir Amid al-Djuyush Abu Ali Hasan ibn Abi Djafar, i al cap d'uns mesos es va signar un tractat amb el cap kurd rival pel qual es va declarar vassall hasanwàyhida i va recuperar Hulwan (1007) o en tot cas abans del 1010, perquè segon Ibn al-Athir va morir aquest any en aquesta ciutat.

El va succeir a Hulwan el seu fill Hisam al-Din Abu l-Shawk Faris, però altres germans van obtenir alguns territoris: Muhalhil ibn Muhammad a Shahrazur, i Surkhab ibn Muhammad a Bandanidjin (Mandali) al sud, prop dels territoris dels luris.

Referències
 Article sobre els annàzides a Encyclopaedia Iranica

Governants
Polítics kurds

redpajama_set_name: RedPajamaWikipedia


text:
Q: vba excel autofit a region excluding several cells I want to autofit columns A:C without considering cells B2:B6 (I want those cells to contain long strings).
Is there a way to tell excel to ignore those cells when autofitting?
Thanks,
Li

A: This does what you want. You could also modify to autofit the Selected cells:
Sub Fit_Column_to_Some_Cells()
Dim rng As Excel.Range
Set rng = ActiveSheet.Range("$A:$A,$C:$C,$B$1,$B$7:$B$1048576")
rng.Columns.AutoFit
End Sub

A: Using a macro:

*

*save B2:B6 elsewhere

*autofit cols A thru C

*restore B2 thru B6 from your temporary storage.

redpajama_set_name: RedPajamaStackExchange


Protesters gather in New York City in May. By Michael Fleshman.
Today's puzzler is short and sweet: How is it possible that no government, including the United States, has been able to recover the 276 Nigerian school girls who were kidnapped by Boko Haram in April?
How about, No one really wants to? For instance, from the point of view of the United States, the girls are (1) far away, (2) Black, and (3) not Americans or related to Americans. If only slavery had not been abolished! Then they might be seen as valuable commodities.
Well, they are far away, in an area that has difficult terrain, which militants not the state largely control, near porous borders with several other states, and they have by all account been split up or even "sold off" individually. Negotiation has the potential to recover some of them, but there is not much that Nigeria or others like the US can offer as leverage in a deal.
Even though the US was offering technical assistance, the Nigerian military ultimately had to recover the girls itself. However, it can rarely prevent Boko Haram from taking territory, its primary purpose, and so it's not surprising its underpaid soldiers were unwilling/unable to undertake a risky search and rescue mission. State penetration is so weak in northeastern Nigeria that Boko Haram has thousands of square miles in which to hide the girls.
As Andy pointed out, Boko Haram has likely already split the girls into smaller groups, and identifying them and recovering them in a very violent war zone is near impossible. Finally, Boko Haram is a very diffuse organization, so negotiations were unlikely to succeed; it's not clear any one person can speak for all of Boko Haram or even most of it.


text:
Croatia stretches along the Adriatic and is home to over 1,000 islands – some of which are among the most charming in Europe. The country is also home to 7 UNESCO World Heritage Sites, which include dramatic, centuries-old towns that continue to win the hearts of travelers as well as filmmakers for their magnificence and well-preserved architecture.
The Croatian countryside offers an abundance in natural beauty, with numerous old-world wine regions that date back to Ancient Greek settlers. Besides offering an impressive history with numerous sites that you can visit and admire up close, Croatia is a cultural melting pot – it's right at the intersection between Central and Southeast Europe, bordering countries like Slovenia, Hungary, Serbia, and Montenegro.
Top destinations in Croatia
Dubrovnik overlooks the Adriatic Sea in southern Croatia, and its Old Town is one of the most beautiful in the world. Encircled by 10th-century walls, its labyrinthine streets are pleasant places to wander, and many of its historical buildings are still in remarkably great shape. The Stradun is the main thoroughfare – an elegant strip full of cafes and stately...
Zagreb treats you to a colorful European cityscape that is rich in old-world architecture and charming medieval vibes. Walking down the city's neat and cobbled streets, you have Gothic cathedrals with vividly colored roofs and magnificent towers dating back...
Split rests on the cerulean waters of the Adriatic Sea. Here, within the still-inhabited Roman Ruins of Diocletian's Palace, you'll find bell tower views from the Cathedral of St. Domnius and many bustling labyrinthine passageways overflowing with lively music...
Trending now in Croatia
10 Best Things to Do in Split
Split, located on the Dalmatian coast in Croatia, is a vibrant port city well-known for its ancient center, beautiful architecture, and exquisite cuisine. Whether you wish to admire impressive Roman monuments, spend the day on a picturesque beach with crystal-clear waters, or walk along one of the most beautiful promenades on the Adriatic Coast, Split has...
10 Best Things to Do in Rovinj
Rovinj has become synonymous with summer getaways full of crystalline waters, cobblestone laneway and a healthy dose of nature....
5 Shopping Experiences in Porec
Shopping in Porec, you'll enter a world filled with local artwork and handcrafted items, super souvenirs to take...
5 Best Nightlife in Zadar
The nightlife in Zadar is relaxed and unpretentious, and on warm evenings people spill out into the streets to enjoy...
10 Souvenirs People Love from Split
There are many different types of souvenirs from Split, a gorgeous coastal Croatian city that's famed for its mixture of...
5 Best Restaurants in Zadar
Zadar's beautiful coastal location makes it an excellent destination for seafood lovers. The waters of the Adriatic provide plenty of...
6 Best Restaurants in Rovinj
Rovinj is a foodie town quickly gaining international interest, known for producing spectacular wines, olive oils and truffles. The...
5 Best Places to Go Shopping in Rovinj
If you're planning to shop in Rovinj, make sure to stock up on Croatian wine and local liqueurs. Some...
8 Instagrammable Places in Split
Split is rich with photogenic spots thanks to the wealth of Roman ruins that you can find scattered throughout the...
10 Best Restaurants in Dubrovnik
Dubrovnik's dining scene is similar to what you'll find in many countries along the Adriatic Sea. The seafood-heavy...
10 Best Nightlife Experiences in Split
Split's nightlife allows you to see this Croatian city in a different light. While it's known for its rich culture...
5 Best Nightlife in Hvar
Nightlife in Hvar attracts thousands of dancing revellers each year as the island is packed with bars and clubs. Featuring...
5 Best Restaurants in Porec
Porec offers an amazing array of dining experiences, from traditional Croatian dishes served in cozy, romantic settings to light...
5 Best Nightlife in Pula
Pula's top nightlife spots liven up the historical city come sunset, with dozens of clubs and bars opening their...
5 Best Restaurants in Hvar
Dining in Hvar promises a combination of Croatian food and culture. Surrounded by the Adriatic Sea, the lush landscape...
10 Places Locals Love to Eat in Split
Dining in Split is a joy for those who like to stray off the well-trod tourist track and delve into...
5 Best Places to Go Shopping in Dubrovnik
When it comes to shopping in Dubrovnik, you'll be forgiven for thinking that, compared to the history, beauty...
5 Best Restaurants in Pula
The best restaurants in Pula have a long-standing reputation for producing amazing Croatian dishes. The culinary traditions of Istria have...
Browse Croatia by category


Bosra castle is situated to the east of Daraa province, 850 meters above the sea level, and it is considered as one of the most famous citadels which were built in the Nabataean reign, in addition to its amphitheater.
Al-Adiliyah Madrasa (school) is an integrated architectural building, as described by dozens of writers and historians in their articles and studies, and one of the oldest and most famous archaeological and cultural landmarks in Damascus.
More than 100 paintings by cartoonists from 67 countries participated in the 15th International Cartoon Contest ,Syria 2019, hosted by the Damascus-based Opera House.
In the heart of al-Qanawat neighborhood in Damascus, a house of small wooden door leads you to a world that stores beautiful memories and traditions through more than 2000 rare artistic pieces collected by the 60-year old Haitham Tabakhah (Abu Mohammad).
Long feature Syrian movie "War Travelers" has won the best Arab film award at the 3rd edition of Sharm El-Sheikh Asian Film Festival (SAFF) for 2019.
Many foreign media delegations are still flocking to the historical Syrian city of Palmyra to prepare films and documentaries on the crimes perpetrated by Daesh (ISIS) terrorist organization against civilians and the history of the archeological city.
Amid buildings and modern shops and down the road from the parliament, al-Rawda café in al-Abed Street in Damascus, for more than 80 years, still retains its identity as a socio-cultural forum.
Hama province has been always famous for its archeological watermills since the first century B.C. as they have been used near the rivers, creeks, springs and ever-flowing falls and some of them still exist today on the banks of the Orontes River adding an aesthetic value to the city.
With the great development of our societies and the appearance of plastic, metal and glass utensils that meet the requirements of modern life, the use of straw trays for decorative purposes has been limited to certain villages and rural areas that still preserve this industry which is inherited by successive generations.
Natural silk industry is one of the most important images of coastal natural heritage where mulberry-trees are the sole source of food for the silk worm.


text:
Simpletools - High performance / modern web application framework
========================================

Simpletools provides you with all tools you need to design and build simple and complex application, taking care of performance optimisation and security for you.

See [https://www.getsimpletools.com/](https://www.getsimpletools.com/) for more information and documentation.

License
-------

Simpletools is licensed under the BSD License - see the LICENSE file for details


text:
Acqua e sapone est un film italien réalisé par Carlo Verdone, sorti en 1983.

Synopsis

Fiche technique
 Titre : Acqua e sapone
 Réalisation : Carlo Verdone
 Scénario : Carlo Verdone, Franco Ferrini et Enrico Oldoini
 Photographie : Danilo Desideri
 Musique : Fabio Liberatori
 Production : Mario Cecchi Gori et Vittorio Cecchi Gori
 Pays d'origine : Italie
 Genre : comédie
 Date de sortie : 1983

Distribution
 Carlo Verdone : Rolando Ferrazza
 Natasha Hovey : Sandy Walsh
 Glenn Saxson : Ted
 Elena Fabrizi : Sora Ines
 Fabrizio Bracconeri : Enzo
 Michele Mirabella : Guidi
 Florinda Bolkan : Wilma Walsh, la mère de Sandy

Lien externe

Film italien sorti en 1983
Comédie italienne
Film réalisé par Carlo Verdone
Film produit par Mario Cecchi Gori
Film tourné dans le quartier de l'EUR