Though arguably somewhat off-topic for CodeProject, this article examines the increasingly heated debate over technology outsourcing—in particular, offshore outsourcing of software development jobs. While this article is sure to provoke a fusillade of flames and impassioned rhetoric, the offshore outsourcing issue must be rationally evaluated by all professional software developers, as it has career implications for almost all of us.
I am merely a (very) amateur economist and experienced programmer, with free-market tendencies and a fierce libertarian streak. However weak my economics and policy background may be, I feel a pragmatic voice with in-the-trenches knowledge of the software development profession is somewhat lacking thus far in the offshore coding debate. Herein lies my presumptuous attempt to catalyze that voice.
Though it is not a new concept, the offshore outsourcing of IT work, in particular software development, has received increased attention of late from all corners, including IT industry pundits, analyst firms such as Gartner, corporations in established countries considering or engaging in outsourcing and offshore coding, many of the companies that provide such outsourcing services, as well as rank-and-file IT professionals in established countries, fearing for their jobs as they are "replaced" by cheaper labor.
Typically, the argument from the corporate perspective is thus: Offshore programmers in emerging economies like India, Southeast Asia, China, etc., work for substantially less than their US and European counterparts, while producing code of equal or greater quality. Therefore, in an economic climate that demands cost cutting wherever possible, it makes complete sense to move as much work as possible offshore.
Of course, those companies that provide offshore outsourcing services, such as Wipro, do nothing to discourage their prospective clients from taking this view. Indeed, no doubt many readers have heard management discussing this very option, as though it presents an ingenious way to get around the unpleasantly long six-month development schedule they have just been presented.
On the other side of the table, rank-and-file programmers often (but not always) take a somewhat more pessimistic viewpoint: Cheap laborers from undeveloped countries are stealing domestic programming jobs and gutting the domestic job market, much as they did to the manufacturing sector in the last century.
Given this unsettling prospect, a number of professionals adopt a protectionist stance, choosing to view their colleagues in Asia and India as opportunistic thieves and charlatans, tricking gullible management into the Devil’s Bargain that is offshore coding.
The canonical example: Manufacturing
Those who fear offshore coding, often cite the experiences of the manufacturing sector during the latter half of the 20th century. Since this particular discussion is still the subject of heated debate, any "objective" analysis which provides any insight is necessarily debatable, however the comparison is so instructive that it’s worth stepping on a few toes to examine the subject.
Basically, Japan and then China and other emerging economies began to compete with American manufacturers in the latter 20th century, producing goods in greater quantities, at substantially lower cost. These goods included not only Japanese automobiles and consumer electronics, but clothing, toys, consumer products, etc.
The cost reductions realized by the foreign manufacturers arose from two advantages: increased efficiency, and cheaper labor. In some cases, unskilled factory workers earned orders of magnitude less than their American counterparts, while working longer hours in largely unregulated working conditions.
While the human rights issue of the treatment of workers is relevant here, the point is this: foreign manufacturers could produce the goods Americans and Europeans needed, at a substantially lower cost. As a result, competitive pressures depressed the American and European manufacturing sectors, with many fearing that the developed world would become utterly dependent upon Japan and the emerging economies of China and Southeast Asia for all its worldly goods.
Of course, in the end, this did not happen. China is a large and growing manufacturing powerhouse, and Japan is the world’s 2nd largest economy, yet the US is still an economic superpower, with a substantial manufacturing industry of its own, and Japan is only now emerging from 10 years of deflation and stagnation. Thus, we must conclude that those who dismiss offshore coding as a fad, and those who herald it as the end of the world, are equally incorrect.
While comparing the offshore coding trend to the history of offshore manufacturing in this way is instructive, we will discover that significant differences exist, which prevent a simplistic comparison between the two. Nonetheless, the insight gained from the offshore manufacturing trend applies just as well to the offshore coding trend emerging now.
Though much of the negative press associated with offshore coding focuses on the loss of domestic jobs, the objective economic perspective actually yields two equally important questions:
First, what is the economic impact of replacing domestic programmers with their offshore counterparts?
Second, what is the net gain (or loss) realized by the domestic corporations engaging in offshore coding?
The @$#!%&* steal our jobs…
Adam Smith, the father of modern economics, wrote in his seminal work "The Wealth of Nations" that (to paraphrase) it is self-evident that it is more efficient and therefore economically better to buy that which one cannot make cheaper oneself. This principle is likely obvious to almost everyone.
For example, it is obviously more efficient for most people to buy flour than to grow, cultivate, and grind wheat to produce their own. Similarly, it is far more economical to buy a color TV from Best Buy or JC Penny than to attempt to construct one yourself. In both of these cases, one could probably produce the good oneself, but it would take time and money that could be more efficiently spent elsewhere, in ways that more directly benefit the economy and the individual.
According to Smith, this principle extends from individuals and households to entire countries. That is, if US consumers want cellular phones, and India can produce the same cellular phone for US$ 10 that US companies can produce for US$ 100, it is generally better for the economies of both India and the US if the US consumers purchase the Indian cellular phone.
The justifications of this assertion are ample:
The benefits to the Indian economy are somewhat obvious, as it benefits from US economic prosperity as US consumers buy more phones. In particular, the example above benefits the Indian people, as it grows the Indian economy, creating jobs, increasing demand (and thus, pay) for skilled workers, which in turn will seek to enjoy their new middle-class lifestyle by spending more in the local economy, paying more taxes, etc.
Further, the US economy benefits in this example, in a number of ways.
First, more US consumers will be able to afford the cellular phone, and therefore pay the sales and other consumption taxes on the phone. In this case, the old example of selling 1000 of something for $1 being better than selling 100 of something for $5 is very applicable, particular as it relates to the tax revenue which of course stays within the US and local economies.
Second, it forces the US cellular phone manufacturers to increase their efficiency, or close down. A more efficient manufacturer will consume fewer economic resources for equivalent output, (re)gain competitive advantage, reduce costs, and may even increase profitability. The alternative, though somewhat cold-hearted, is also positive, as it frees the resources (including workers) consumed by the inefficient and uncompetitive US cellular phone manufacturer, for use by more efficient and economically beneficial endeavors.
This contrived example applies equally well to onshore vs. offshore coding. To contrive another example, if a software company, Evil Empire Inc., can produce its software, World Dominationware, at a cost of US$ 1 million using domestic programmers, or US$ 100,000 using offshore programmers producing software of equal quality, Evil Empire Inc.’s executives have little economic reason to choose the domestic programmers.
As a result of this, Evil Empire can sell its software at a lower cost and higher profit, yielding more tax revenue, increased wealth for its shareholders, faster and more significant growth, and thus increased payrolls (though likely not including many programmers).
Thus, the assertion of this section is that Adam Smith is correct, and that his theory applies as much to wheat flour as it does to programming. While the local consequences of offshore coding may be negative (job loss and the ensuing unemployment), these can be overcome (see below), and the net result at the macro level is generally positive for both economies.
Note, however, that there are exceptions. If a country were populated entirely by programmers who had no other skills, and another country began taking their jobs by offering a cheaper product of equal quality, the country of programmers would likely suffer economically. However, this can hardly be seen as an injustice: if one cannot provide a competitive service (that is, if other countries can provide programming services for less than our hypothetical nation of programmers), one should not be surprised when one’s customers go elsewhere.
Further, at the micro level, those employees who lose their jobs are obviously not benefiting, at least initially. Though it may seem cold-hearted, the same maxim in the previous paragraph applies to individuals as well: if one demands more for the same service than someone else, it should come as no surprise when the cheaper price prevails.
In much the same way, imagine a junior programmer applying for an entry-level programming position, and demanding US$ 120,000/year. Is it a profound injustice when the employer selects a different, equally qualified candidate asking for US$ 40,000/year?
This issue of micro-level consequences and the associated solutions will be examined further in the following sections.
Offshore coding and the blessed bottom line
The previous section discussed the economic impacts of offshore coding on the host and client countries and their citizens, however the discussion was based on the assumption that domestic and offshore programmers produced identical (or at least equivalent) products, differing only in cost.
As most programmers are likely aware, this may apply to the manufacture of children’s toys and toasters, but software development is much more complex, therefore assuming equivalence of output is a convenient theoretical abstraction that has very little relevance in practice. In this section, I present a more pragmatic discussion of the costs and benefits of offshore coding, grounded at least tenuously in reality.
Corporations, executives, and other scourges
As much as we may distrust and despise money-hungry, soulless mega-corporations and the money-hungry, soulless executives who run them, we must acknowledge one thing: corporations (and their leaders) have a moral and legal obligation to make money for their shareholders. While this does not condone illegal activities ala Enron, it does condone any legal activity that stands to benefit the corporation and thus its shareholders.
Therefore, before this discussion really begins, it must be acknowledged that corporations do not have an inherent duty to their employees to employ them, to refrain from replacing them with machines or cheaper employees, or to subsidize inefficient workers. While many will argue that corporations have a social obligation to the communities in which they operate (and to an extent they do), this does not forbid the lawful use of more efficient resources to perform the same tasks.
That said, an exception to this rule arises when one considers unions. However, a corporation’s obligations to its unions are not inherent, but rather contractual. Similarly, if I could convince my employer to sign a document obligating her to employ me for the duration of my life, and barring her from ever questioning my efficiency or value, she would then have an obligation to do so. Of course, more likely she will fire me and find an employee who is not so unreasonable, which is also her right.
Having established that corporations serve their shareholders and not their employees, let us now examine the practical costs and benefits of outsourcing.
In a free-market economy, the market decides who wins and who loses. While factors like quality, cost, and availability influence market success, so do less tangible factors like public perception and reputation.
While offshore coding may make great financial sense, it may cost more in public opinion than it saves in dollars. In general, the populous does not like to lose jobs to foreigners, particularly when the foreigners are paid substantially less and thus undercut domestic labor substantially. This may result in a serious back-lash in the public’s opinion of the domestic corporation doing the outsourcing.
As an example, consider the (mild) outcry over the state of New Jersey’s decision to outsource welfare processing to a call center in India. From a fiscal perspective, this made complete sense, particularly for a cash-strapped state suffering from serious budget deficits. Unfortunately, if the public resents the decision enough to create a significant outcry, they may also vote (with their dollars or their votes) to punish the perpetrators.
Thus, a corporation considering offshore coding must consider the sensitivities of its customers, the public at large, and the domestic governments who are sometimes hostile to corporate interests. This may be a significant concern for corporations that deal directly and visibly with the public, and virtually no concern for corporations with a very low profile.
Closely related to the issue of public opinion is that of employee morale. While we’ve established that corporations do not owe continued employment to their employees, corporations do have a selfish interest in keeping employee morale high. Not only does high morale improve productivity, it reduces turnover, and likely increases access to qualified workers interested in working in a positive environment.
Thus, when a corporation announces it will replace 10% of its domestic workforce with offshore labor at 1/4th the cost, morale likely takes a hit as employees realize that the concept of a corporate/employee relationship as being familial or custodial is largely fictional, and a frequent casualty of budget cuts and financial pressures. As a result, their loyalty to the corporation may wane, increasing turnover and decreasing productivity. Thus, the cost savings realized by moving the 10% of the workforce offshore, may be countered by a cost increase from the other 90%, as they reduce output and increase turnover, and a loss in competitive advantage as highly qualified workers go elsewhere for their interviews.
Programmers as cogs
During the industrial revolution, as manufacturing grew into an economic powerhouse of an industry driven by mechanized engines of automation, skilled tradesman became increasingly irrelevant. Instead, cheap and easily exploited immigrants and children could be put to work en masse, with minimal skills or training, and replaced just as easily.
Of course, this enabled the economic and social developments which made the world what it is today, but it also enabled business leaders to view their employees as cogs, which are a minor hassle to replace, but nonetheless easily replaceable by any other cog.
Unfortunately, this mindset seems encoded into the genetic material of managers and executives everywhere. As programmers know, the reality is not so simple. Even assuming that programming is a single discipline, without specializations in networking or GUI or databases, the cold fact of the matter is that the best programmers are in some cases hundreds of times more productive than the worst programmers, and obviously the best programmers are much rarer than the worst.
The result of this reality is that comparing two programmers on the basis of their cost is utterly meaningless. What good is a programmer at 1/10th the price, with 1/100th the productivity?
That said, it is unfair to say that all offshore coders are less capable than all domestic coders; the point is, a programmer’s capabilities--as well as her cost--must be considered when determining value. This is a very difficult problem when hiring domestic programmers, and becomes virtually intractable with offshore coders.
Without some reliable metric (lines of code per dollar per day doesn’t cut it), the ROI of offshore coding cannot be reliably established. Relying on cost alone when making the decision is dangerously close to abdication of fiduciary responsibility, which is not a phrase executives like to hear.
Projects as blueprints
The previous section’s discussion of the origins of the programmers-as-cogs mentality is equally applicable to the related fiction, projects-as-blueprints.
In an industrial setting, a project is typically the design and production of a product; some tangible, physical thing coming off the assembly line. Once a skilled engineer designs the product and produces blueprints or schematics, the unskilled cogs can set to work and produce the product.
Obviously, software is not so simple. Bad programmers can build worthless software from masterful designs, and good programmers can (sometimes) rescue abysmal designs through masterful programming. In either case, the skilled labor is distributed evenly across the product lifecycle, and is not concentrated on the design phase as is the case with manufactured goods. Further, the design and production teams are not decoupled; each must interact constantly with the other, to ensure the product being built and the product being designed are indeed the same product, and the best product it can be (and even that the product is what the customer actually wants).
As a result of this tightly linked lifecycle, it is difficult to find one point at which the skilled laborers are done, and the offshore cogs can take over and begin production. Therefore, the offshore coders must actually be an integral part of the product lifecycle, as skilled and competent as any other participant.
Having established this fact leads us to the next point:
Assume for this discussion that all offshore coders are fluent speakers of the domestic language. Not only is this often the case, but a language barrier is the least of the communication problems associated with offshore outsourcing.
Given the realization from the previous section that offshore coders must be as much involved with a product as the designers, stakeholders, end users, and testers, it becomes clear that offshore coding does not mean requirements can be gathered, e-mailed across the globe, and expected to come back as a polished product.
Instead, the same bothersome collaboration and feedback loops used by domestic development teams must extend to the offshore coders. This is complicated by the distance (as great as telecommuting is, when it comes to meeting to discuss development projects, there’s no substitute for being there), time difference, a lack of understanding of domain-specific factors, and the usual problems of wasteful, unproductive meetings, conflicting goals, poorly-defined objectives and stakeholders, shifting requirements, etc.
These problems are significantly amplified when agile methods such as eXtreme Programming are employed to develop in so-called "real time". One of XP’s principles is that the design forms from the code, and that frequent deliverables yield iterative user feedback which leads to an ad-hoc discovery of requirements, and management of requirements changes. Therefore, "real time" communication between all participants in the development process is critical; when communication breaks down, risk increases and the probability of success plummets.
Thus, those considering offshore coding must realize the following caveats with regard to communications:
First, the only cost savings will be the cost of the programmers, testers, etc. that are moved offshore. Project managers, internal QA staff, support and maintenance personnel, and project stakeholders stay in-country, and stay involved.
Second, collaborative barriers actually increase management overhead, likely adding to the time required by stakeholders, end users, and often highly-paid internal architects and designers. This must be subtracted from the cost savings.
Third, offshore coding does not eliminate the most intractable elements of software development, including the project management principles that are routinely ignored in domestic development projects. Indeed, when it comes to shifting requirements, the collaborative barriers and de-coupling of developers from the rest of the lifecycle associated with offshore coding actually increases cost and hassle.
Support and maintenance
If programmers did their jobs perfectly, users’ requirements were immutable, and competitive pressures didn’t exist, changes to software would be unnecessary. Sadly, programmers fail, users are fickle, and competition is fierce, therefore software must not only be maintainable, but downright agile.
In addition to the development-time agility problems described above, support, maintenance, and agility after initial development is concluded, are equally important to the long term success (and therefore justification) of any development project. When software is developed in-house by domestic programmers, even if little documentation is developed, it is reasonable to expect the original developers or their successors will be available to support and maintain the product, and modify it in more significant ways as business requirements change.
With outsourced development (offshore or domestic), however, the client is much more insulated from the original developers. In all likelihood, ongoing maintenance and support will require an ongoing contract with the offshore coders, with enhancements likely requiring additional funds. Even in the face of such contracts, the original developers may or may not be available, and if not, their replacements must consume valuable (and expensive) time ramping up to make the changes. Further, the attendant communication problems described above are associated with this effort as well, particularly with major enhancement efforts.
For the reasons described in the previous section, it is likely that once the offshore coding decision is made, it "stays made", as moving back in house from offshore will be more expensive than staying in house in the first place.
Due to the structure of the outsourced development effort, the client’s choices end up quite limited. Since the client is decoupled from the individual developers on the project, the client’s view of the offshore coders is an aggregate one; thus, they are either all competent and capable, or not. Thus, a client’s options are to stay with the offshore coding company, or not. By contrast, an internal development team is slightly more transparent, with incompetent individuals more likely to be discovered and replaced, without replacing the entire team and starting over.
Thus, corporations considering outsourcing must realize that if things go sour or don’t turn out, it will be difficult to back out.
When an application is built in-house, it makes sense to perform a code audit for a number of practical reasons, of which one is to ensure the system is secure against accidental security bugs and deliberate back-doors. Unfortunately, this valuable feedback/QA technique is often skipped, for various and irrelevant reasons.
When offshore coders have been employed, code audits become not only a good idea, but mandatory. While a domestic employee might undergo a background check, or face criminal penalties for deliberate subversion of software, offshore coders are usually not vetted for background anomalies, and certainly are not subject to domestic civil and criminal law. Further, the fact that offshore coders work for less money suggests that unscrupulous offshore coders can be compromised for less money.
As a result, a responsible project manager should not accept code from an offshore firm without a comprehensive code audit. Of course, the code audit must be performed by a competent programmer specializing in security audits, which adds substantial cost, and substantial time to the development lifecycle. By contrast, a domestic development team could be used to perform its own code audit, which, combined with background checks and the pain of civil and criminal penalties, mitigates security risks for far less time and money.
What’s left of the bottom line
If, upon consideration of all of the above issues, quantitatively as well as qualitatively, the bottom line of the offshore coding spreadsheet is still black, it likely makes good sense to engage offshore coders in some capacity.
The key point to take from this section is this: the question to ask is not "is offshore coding wrong or bad?", but rather, "will offshore coding make my shareholders richer?". However, from the length of the previous section, and the extent of the caveats, it should be clear that performing a rigorous analysis is complex and time-consuming, and the answer may very well be "stay in house".
What not to do about it
In this section, several proposals are evaluated which have been floated by those who are in some way against offshore coding either as a trend or a practice. For each proposal, one or more reasons are provided explaining why it is a bad idea and should be ignored.
Unionize domestic programmers
For a number of years, some domestic programmers have been calling for unionization, or at least the formation of some sort of trade group providing advocacy on behalf of domestic programmers. Ostensibly, the objective of such groups would be to protect domestic programmers from exploitative corporations, corrupt governments, and job-stealing foreign programmers.
The fundamental flaw with this reasoning is the implied belief that domestic programmers need protection. In effect, those who advocate unionization or trade group organizations are accepting the "programmers as cogs" principle, and then asserting that domestic cogs are special and should receive contractually obligated rights and privileges.
In reality, a programmer’s union is absurd (and would no doubt fail when a majority of programmers refuse to join). A trade group makes sense (indeed the ACM and the IEEE could be counted as trade groups), but rather than advocating protectionist policies, a useful trade group ought to focus on helping its members differentiate themselves in a free market with training, certifications, and other (somewhat) useful benefits. Both the IEEE and ACM provide these benefits in some form.
Adopt protectionist policies
Failing a domestic programmer’s union, the disenchanted programmer labor movement often calls for various forms of protectionist policies. From the almost practical (though utterly indefensible) tax penalties for use of offshore coders, to the utterly absurd classification of offshore coding or the code it produces as an import subject to tariffs and taxes, the idea is to distort the free market calculus that makes offshore coding cost effective, until offshore coding becomes utterly unjustifiable from a financial perspective.
Apart from the argument above, which establishes the economic benefits of any net gain in efficiency--offshore coding included--a more fundamental argument against this policy exists: distortion of market forces towards a particular aim almost inevitably leads to a net economic loss. A recent example here in the US is President Bush’s protectionist steel tariffs, which did little to protect domestic steel producers from foreign competition, and seriously injured those domestic manufacturers who depend upon steel to produce their products, which became absurdly expensive in the face of the rapacious protectionist tariffs.
Effectively, advocacy of protectionist policies is attempting to cure the symptom, not the affliction. If profit-motivated corporations are moving programmer jobs offshore, and domestic programmers don’t like it, they are better served focusing on competing fairly with their offshore counterparts (perhaps not on cost, but on overall value, which as stated above is what really matters), and articulating their advantages over offshore coders.
What to do about it
While the previous section dealt with bad solutions to the offshore coding "problem", this section outlines some strategies that make sense, are practical, and don’t involve punitive market distortion.
The most fundamental strategy in dealing with the offshore coding trend is to adopt a productive attitude. Those who feel as though corporations moving jobs offshore are somehow wronging their employees, or that governments allowing offshore coding to continue are betraying their obligations to their citizens, utterly miss the point.
One must realize that as an actor in a free market economy, market forces determine one’s success or failure as surely as they do a large corporation. That is, each individual must realize that she is in competition with other individuals pursuing the same opportunity, and upon that realization, do what is necessary to distinguish herself from the competition.
Many programmers in particular find this distasteful; indeed, they became programmers because the business stuff was of no interest to them. Unfortunately, there is no choice; actors in a free market must take responsibility for their own success or failure, or face financial ruin. This point bears repeating: Fundamentally, each individual must take personal responsibility for his or her own success, and do what is necessary to ensure it.
In the Economic Perspective section, a discussion of the pros and cons of offshore coding is outlined. The industrious reader will likely see numerous opportunities to differentiate himself from offshore coders, in such a way as can be clearly articulated to management. This type of thinking is mandatory in a free market system; one must look for opportunities, and seize them when they arise.
Of course, some executives and managers may be unconvinced by a particular value proposition. They may be reading breathless articles in trendy business magazines about how their colleagues are saving millions by outsourcing everything except janitorial services to India. However, if they fail to consider all of the caveats above, and fail to recognize a superior value proposition, they likely will be rewarded accordingly. In particular, their competitors may not be so blinded, and may represent another opportunity for the industrious and differentiated programmer.
Arguably, education is a form of differentiation, but I feel it nonetheless warrants explicit mention.
Education can take many forms: college, certification classes, or self-edification projects undertaken to learn a new technology or product. In any case, the underlying theme is the constant learning and development of new knowledge and skills.
The industrious engineer will realize that education must be on-going, regardless of economic climate. This mindset of individual responsibility is extremely important for those who wish to run ahead of the pack. By constantly growing and developing, your value is increased, as are your horizons broadened, and perspectives expanded. When considering education, you needn't limit yourself to technology, but rather you should focus on that which is interesting or exciting, be it a book on C#, a security certification, or a master's degree in economics.
Advocate pro-business policies
A number of factors determine an employee’s cost to an employer, only one of which is salary. Factors like social security, unemployment and worker’s compensation insurance, various OSHA and Department of Labor requirements, and state and local regulations all burden US employers. Other developed countries impose similar burdens. Cost of benefits, like soaring health insurance costs, only add to the load.
Further, while developed countries for the most part have clearly defined commercial laws, the patent, trademark, and copyright laws in the US and much of Europe are largely broken from a technology perspective, leading to unnecessary and expensive use of patent attorneys in defensive patenting strategies, and attacking and defending absurd patents as a means of competitive pressure.
Finally, as much as anti-globalization and socialist activists claim the industrialized world governments are bought and paid for by sinister mega-corporations, the reality is that government has always had a love-hate relationship with business. From the draconian and incoherent US Securities and Exchange Commission, to the rapacious taxes foisted on domestic corporations to punish them for their success, businesses are often treated as second-class citizens by national and local governments that fail to recognize the source of their own economic prosperity.
All of these factors together must be considered when a corporation is evaluating its costs of doing business in a particular country. If citizens of the US or Europe are displeased that this business calculus points to India as a better host, a wise recourse would be to focus on making the US and Europe more appealing, rather than flogging the evil corporations until they once again prefer their domestic tormentors to India or China.
Roll your own opportunity
A fellow free-marketeer, John Cardinal, reminded me of what is perhaps the most compelling "niche" of all: founding and developing your own company. I have done this with Cryptos Mobile Systems, my current company, as have countless other programmers and engineers before me.
The advantages of this approach are several, including:
- Complete control over business and technology; the only stupid fads you suffer are those you embrace yourself
- Potential for substantial wealth; as a founder, you will typically hold a substantial equity stake, and stand to benefit financially if your company is successful
- Relative autonomy in terms of work style, hours, etc., although a startup typically requires absurd amounts of work
- The profound personal satisfaction of controlling one's own destiny, for better or for worse
- Appealing tax perks, like righting off equipment, education, business travel, etc.
Of course, this is also perhaps the most dangerous of all solutions, as job security is virtually non-existent, and you will often not know where the next month's mortgage payment will come from (if at all). Start-ups also require an absurd amount of work, coupled with constant stress, and disturbing uncertainties. To be sure, many readers will not have this option at all, for reasons of financial position, familial obligations, etc. For those who can, however, starting one's own company must be considered.
Another option for those of you readers who have been recently laid off, and have a few months' savings before they have to work again, might be to form your own company, to pursue an idea for a product or technology, or simply to learn about some new technologies or products. With the help of an accountant, buy whatever technology items you need through your business, including education or certification if necessary. While shopping around for your next job, continue to work on your company's project, learning and growing all the while. You might also consider drumming up short-term contract work, run through your company.
Not only does this approach allow you the freedom to develop new skills while between jobs, but it exposes you to the adventurous life of an entrepreneur, without all the attendant risks. Further, should your quest for work drag on, your resume will nonetheless quite honestly reflect contiguous employment, under the banner of your company. This is also a great way to develop professional experience in a technology or product which you haven't otherwise had the opportunity to apply.
Regardless of the approach you take, you are well-advised to at least consider the entrepreneurial route. It is a road fraught with peril, but the potential rewards (financial and otherwise) are substantial.
Find the niches
Taking into consideration the offshore coding caveats above, the industrious reader will realize that offshore coding is completely impractical for a number of scenarios, a few of which are examined below. By focusing on these niche areas, a domestic programmer may find areas where offshore coding does not offer a compelling value proposition.
Small, lightweight projects
The more structured and process-heavy a project, the easier it is to treat individual actors as cogs. It should come as no surprise, then, that offshore coding firms are often very adept at software development process, such as CMM. As any veteran of a top-heavy process knows, heavy process is completely inappropriate for small development teams, as the overhead is not commensurate with any positive gains.
Indeed, small teams often benefit from more ad-hoc, "real time" processes and quasi-processes such as XP and other agile methods. Being as they are more organic and fluid, attempting to use these processes while outsourcing development to offshore coders is very likely to end in an amusing yet spectacular failure.
Therefore, domestic programmers may focus more on small development teams, which are often encountered within startups, or small business units within larger organizations.
For many of the same reasons specified in the previous section, early-stage startups are usually not good candidates for offshore coding. Seldom does one read about a 12-man startup announcing it has outsourced 50% of its three-person development staff to Bangalore. Remember, offshore coding becomes appealing as one reaches a certain economy of scale, which is well above three programmers. By focusing one’s energies on startup opportunities, offshore coding is less likely to pose a threat to one’s ambitions.
For US programmers, the US government has an extensive need for programmers with US citizenship (visas, greencards, etc. are not enough) and security clearances. Other developed countries have similar programs. While obtaining a clearance is a difficult and time-consuming process, the result is strong job security, not only as a government contractor, but also later in the private sector. As security becomes more of an issue, the dubious security of offshore coding will make trustworthy domestic programmers all the more valuable.
While some programmers will consider this option schismatic, the sad reality is that programmers will always be subordinate to management, even if those programmers are offshore. Indeed, offshore coding requires more in-house management, not less.
Focusing on developing one’s management credentials, as well as maintaining one’s tech skills, will add value in any market. Focusing on management of a distributed workforce will render one even more qualified to manage offshore coders.
Due to the gap between offshore coders with general programming knowledge, and the displaced in-house programmers with extensive domain-specific knowledge, so-called business analysts are required for any successful offshore coding engagement. Along with architects, business analysts help define the project, which is then executed by the offshore coders (at least in theory). While outsourcing programmers may make sense, outsourcing strategy almost never does, therefore internal employees with a solid grasp of the domestic corporation’s business, goals, problems, and strategies and possessing the technical skills required to bridge the gap with offshore coders, are likely to remain extremely valuable.
If the prospect of "becoming a business guy" just so one can remain employed is distasteful, a wait-and-see approach may not necessarily be cataclysmic.
While Indians may work for 1/4th what Americans or Europeans make, they make about the same in terms of quality of life and percentage of average per-capita income. That is, Indian programmers making US$ 20,000/year aren’t struggling in poverty as one making US$ 20,000 in America would be; rather, US$ 20,000 buys a great deal more in India, primarily because India is an emerging economy.
However, as the doomsayer’s predictions of millions of IT jobs moving overseas come true, the Indian economy will grow and strengthen, such that US$ 20,000/year won’t be enough anymore. Indeed, already India is facing a shortage of programmers, and China’s burgeoning middle class is becoming increasingly restive and ambitious.
Assuming the US and European economies stagnate, as India and China grow and prosper, the business case for offshore coding will weaken. How long this will take, or how much India or China have to grow before this happens, is not clear. However, given all of the caveats of offshore outsourcing, the net savings is not likely to be close to 75%, which means that as the cost of Indian programmers increases from 1/4th a US programmer to 1/2 or 3/4ths a US programmer, the net cost of offshore outsourcing is likely to become sufficiently high as to negate any potential savings in labor costs.
Of course, if the US and European economies do not stagnate, one ought not worry, as an industrious individual should be able to find rewarding work in a growing economy, regardless of offshore outsourcing pressures.
This article has made some potentially inflammatory but ultimately defensible assertions.
First, outsourcing work to offshore workers who are cheaper and equally capable as domestic workers makes good financial sense, and is not inherently immoral.
Second, corporations owe no duty of loyalty or employment to their employees, and can (indeed, should) seek the most efficient and effective way to perform a given task, regardless of physical location.
Third, offshore outsourcing of programming jobs is potentially perilous domestic companies' bottom lines, and must be considered in terms of total qualitative and quantitative cost, not simply the US$ 20,000/year the Indian programmer makes.
Fourth, an industrious domestic programmer concerned about competition from offshore coders must resist the temptation to sulk and blame others, and should instead endeavor to differentiate himself such that offshore coders cannot compete with him.
Hopefully, the reader is at least enraged, or at best inspired to action, as a result of reading this article. Those who wish to deny the realities of free market economics may return their heads to the sand, but they do so at their own peril.
- September 30, 2003 - Initial publication
- October 26, 2003 - Updated to reflect more accurate Indian salary numbers (thanks Nishant S.), and to discuss the advantages and disadvantages of forming one's own company to avoid the outsourcing axe (thanks John Cardinal)


Karen just got home from the supermarket, and is getting ready to go to sleep.

After taking a shower and changing into her pajamas, she looked at her shelf and saw an album. Curious, she opened it and saw a trading card collection.

She recalled that she used to play with those cards as a child, and, although she is now grown-up, she still wonders a few things about it.

Each card has three characteristics: strength, defense and speed. The values of all characteristics of all cards are positive integers. The maximum possible strength any card can have is p, the maximum possible defense is q and the maximum possible speed is r.

There are n cards in her collection. The i-th card has a strength ai, defense bi and speed ci, respectively.

A card beats another card if at least two of its characteristics are strictly greater than the corresponding characteristics of the other card.

She now wonders how many different cards can beat all the cards in her collection. Two cards are considered different if at least one of their characteristics have different values.


Windows Embedded Family Product Support Lifecycle FAQ
1. How is this offering different from the Windows Embedded extended hotfix program that was announced in March 2002?
Microsoft believes that the new comprehensive Support Lifecycle policy for all Windows products provides even more benefits to Windows Embedded customers. Specifically, the Microsoft Lifecycle policy update of June 1, 2004, provides support for a minimum of 10 years after a product’s general availability date. Companies can now request no-charge hotfixes and receive traditional support for the first 5 years (as compared to 4 years in the prior program). After the mainstream support period, companies can receive traditional paid support and security update support for a minimum of 5 years of extended support. This is a total combined time of 10 years. Customers who want to request hotfixes that are not security-related must sign up for an extended hotfix support agreement within 90 days of the end of mainstream support for a product.
2. Can I install and ship on my devices a hotfix that was requested during the extended support period?
Yes. All embedded hotfixes are considered distributable and are available to be shipped on embedded devices.
Note that there is an associated fee for hotfixes that are not security-related but that are requested and provided during the extended support period.
3. Is any support available after the extended support period?
Many free and non-Microsoft support options are available for Windows Embedded products. Specifically, these options includeWindows CE Shared Source, Windows Embedded newsgroups, online chats with Windows Embedded experts, and services that are provided by Windows Embedded partners. These options will continue for a product after the extended period has expired.


We are Liquibase
Liquibase is the leader in the database release automation segment of the more broadly defined DevOps market. Our vision is to be the easiest, safest, and most powerful community-led database change management solution. Downloaded more than 45 million times, our software enables DevOps teams around the globe to accelerate the software delivery process by automating database updates. As companies of all sizes continue to adopt an agile methodology and DevOps practices, there is a growing realization that the database needs to be considered as part of this innovation process.
A career at Liquibase means joining a quickly growing company on the front lines of the DevOps space. You can expect to revel in growth across the board — in the number of customers we support, in the experiments we run, in the scope and complexity of our technical projects, and the list goes on.
At Liquibase, we foster a culture rooted in the open-source values of freedom, choice, transparency, and meritocracy. These are not just fashion labels here, but sincere convictions, and you’ll see that reflected in the way we operate daily. We’re caffeinated, collaborative & confident experts, eager to solve the most challenging database CI/CD problems for our customers.
Want to help the software world move faster? You’ve found the right place.
What you’ll do:
- Support our SaaS products
- Responsible for the CICD build & deployment of SaaS applications to multiple Amazon AWS accounts
- Improve health & threat detection monitoring for hosted applications
- Improve Monitoring and Logging of our SaaS applications
- Follow security best practices
- Help us continue to improve our development and test automation
- Docker-ize applications and databases.
- Build CICD Pipelines in Jenkins and Github Actions
- Migrate manual systems to automated systems using tools like Packer, Ansible, and Terraform.
- Bring in systems and tools that enable our teams to work better
What we’re looking for:
- Foundational, real-world work experience with DevOps and SaaS Site Reliability. You don’t have to be an expert, but you should be confident in your ability to solve DevOps and systems related problems.
- One or more years of experience with the following tools/systems:
- AWS, specifically Elastic Beanstalk, ECS, and EKS
- Monitoring Platforms such as New Relic and DataDog
- Logging Platforms such as Sumo Logic, Splunk, and ELK Stack
- Building CICD Pipelines using tools such as Github Actions and Jenkins
- Scripting (bash, groovy, python)
- Linux and Windows
- Relational databases (Postgres, MySQL, Oracle, SQL Server, etc.)
- Jira and Confluence
- A strong understanding of Security and Best Practices in both SaaS and on-prem applications.
- A desire to document well
- A Bachelor’s degree or relevant work experience is required.
- AWS Certifications are a plus.
Perks of Life at Liquibase:
- A transparent and collaborative team environment. We value multiple perspectives and fresh thinking
- Our entrepreneurial culture provides every employee the opportunity to make a meaningful impact
- You get to work on new technologies and learn from experienced engineers
- You gain insight into how some of the world’s largest brands manage software teams and releases
- Growth opportunities and ability to move up within company
- Everyone is a shareholder in the company
- Flexibility of remote work
- Generous company paid stipend towards benefits
- Flexible Time Off and Paid Holidays
- No punks, No jerks


You are given n segments on the Ox-axis. You can drive a nail in any integer point on the Ox-axis line nail so, that all segments containing this point, are considered nailed down. If the nail passes through endpoint of some segment, this segment is considered to be nailed too. What is the smallest number of nails needed to nail all the segments down?


/*
Copyright (C) 2014 insane coder (http://insanecoding.blogspot.com/, http://asprintf.insanecoding.org/)

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "asprintf.h"

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int asprintf(char **strp, const char *fmt, ...)
{
  int r;
  va_list ap;
  va_start(ap, fmt);
  r = vasprintf(strp, fmt, ap);
  va_end(ap);
  return(r);
}

int vasprintf(char **strp, const char *fmt, va_list ap)
{
  int r = -1, size = _vscprintf(fmt, ap);
  if ((size >= 0) && (size < INT_MAX))
  {
    *strp = (char *)malloc(size+1); //+1 for null
    if (*strp)
    {
      r = vsnprintf(*strp, size+1, fmt, ap);  //+1 for null
      if (r == -1) { insane_free(*strp); }
    }
  }
  else { *strp = 0; }
  return(r);
}


Joe Celko's Trees And Hierarchies In Sql For Smarties (the Morgan Kaufmann Series In Data Management Systems)
by Joe Celko /
2004 / English / PDF
4.8 MB Download
Joe Celko's Trees and Hierarchies in SQL is an intermediate to advanced-level practitioner's guide to mastering the two most challenging aspects of developing database applications in SQL. In this book, Celko illustrates several major approaches to representing trees and hierarchies and related topics that should be of interest to the working database programmer.


The mobile application store has a new game called "Subway Roller".

The protagonist of the game Philip is located in one end of the tunnel and wants to get out of the other one. The tunnel is a rectangular field consisting of three rows and n columns. At the beginning of the game the hero is in some cell of the leftmost column. Some number of trains rides towards the hero. Each train consists of two or more neighbouring cells in some row of the field.

All trains are moving from right to left at a speed of two cells per second, and the hero runs from left to right at the speed of one cell per second. For simplicity, the game is implemented so that the hero and the trains move in turns. First, the hero moves one cell to the right, then one square up or down, or stays idle. Then all the trains move twice simultaneously one cell to the left. Thus, in one move, Philip definitely makes a move to the right and can move up or down. If at any point, Philip is in the same cell with a train, he loses. If the train reaches the left column, it continues to move as before, leaving the tunnel.

Your task is to answer the question whether there is a sequence of movements of Philip, such that he would be able to get to the rightmost column.


You like numbers, don't you? Nastia has a lot of numbers and she wants to share them with you! Isn't it amazing?

Let $$$a_i$$$ be how many numbers $$$i$$$ ($$$1 \le i \le k$$$) you have.

An $$$n \times n$$$ matrix is called beautiful if it contains all the numbers you have, and for each $$$2 \times 2$$$ submatrix of the original matrix is satisfied:

1. The number of occupied cells doesn't exceed $$$3$$$;
2. The numbers on each diagonal are distinct.

Make a beautiful matrix of minimum size.


Free Peer Connect Summit
Expert days with analysts
Additional practical resources that add to Gartner research and analyst discussions
Providing visibility into what their peers are doing
Peer document sharing
Top status in the IT industry
Fresh insights, different perspectives, new ideas
You can get maximum value from Peer Connect by browsing the forums; no participation required to get the most for your investment
Leverage discussions before asking questions, and search for related discussions to join and contribute to help also help others.
Asking good questions will help get good answers.


I'm quite new to TT after moving over from Artisteer. I'm trying to recreate one of my artisteer templates but I appear to be struggling somewhat due to a lack of features. What I need to be able to do is to edit a table after I've created it in case I want to add/remove rows, borders etc. I also need the ability to be able to edit the html within a column.
I'm hoping that this is possible otherwise without these features this software is pretty much useless to me and I've just spent a lot of money on incomplete software I can't use.
The only option I can see if I can't edit the table is to have to edit the css AFTER the project is finished which, to be honest, will be a massive pain in the arse for me!
Hopefully someone can point me in the right direction - thanks guys!


ImageBoss does compression on the fly.
WebP & AVIF
When using this option, ImageBoss analyzes if the user's device supports WebP or AVIF and delivers the image with smallest image format to your user.
WebP/AVIF formats can reduce file size up to 60%.
No need to do anything. By default all images are compressed and cached to ensure optimal user experience to all ImageBoss users. Expect different levels of compression depending of the image format.
Disabling Compressiontrue, false (defaults to true).
https://img.imageboss.me /mywebsite /width /500 /examples/01.jpg
Send us a message to support[at]imageboss.me if you have any doubts.


Having said that, if failing to help make a link is considered an error, then a failure ought to toss an exception.
A operate specifies an action or simply a computation that usually takes the program from one steady point out to the subsequent. It is actually the fundamental constructing block of plans.
However due to the economic downturn the area bookings as well as the gatherings have lessened immensely. Hence to overcome the result on the recession as well as the competition, resort’s advertising Division has think of the marketing approach.
Importantly, the rules guidance gradual adoption: It is often infeasible to fully convert a large code foundation abruptly.
Just before choosing that you cannot pay for or don’t like exception-centered error dealing with, Possess a look at the possibilities;
When the internet marketing plan has taken The form which is executed, the article completion critique in the job is finished. The evaluate is done on The premise of your time and cost.
-- getCharge is in Movie. It employs a switch according to the movie's class while in the cost calculation. If a fresh group is added the switch will require up-to-date.
We've been uncomfortable with policies that simply informative post just state “don’t do that!” without having presenting another.
The associated fee involved is minimal because the mails are sent by e-mails. The direct mailing to the prevailing and potential prospects are going to be cost effective way of promoting.
Passing an uninitialized variable for a reference to non-const argument is often assumed to generally be a write into the variable.
an arbitrary variety of unnamed and named parameters, and obtain them via an in-put listing of arguments *args and
(McIvor, R. & Humphreys, P& Mc Aleer, W. (1997). A different lawful challenge could be the termination of deal, in this article the two the get-togethers indication an settlement or maybe a contract which mentions that in case the lodge will not just like the do the job or even the function ethics of the provider, they have ideal to terminate the expert services and would pay back just for the authorised operate by them. (Mulgan Richard 1997). One of several lawful issues is definitely the possession legal rights; below the proprietor that's the supplier is supplied the appropriate to generate some modifications eventually solution and likewise to possess the item, on the other hand, all the main use legal rights is Using the resort. The supplier keeps the tights to use the function to show case in his portfolio.
To avoid slicing, as the normal duplicate functions will duplicate just the foundation percentage of a derived object.
In this kind of instances, localize the use of necessary extensions and Handle their my site use with non-Main Coding Pointers. If at all possible, Make interfaces that encapsulate the extensions so they may be turned off or compiled absent on devices that don't assist People extensions.


#pragma once
////////////////////////////////////////////////////////////////////////////////
//Copyright (c) 2012, Ugo Varetto
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//    * Redistributions of source code must retain the above copyright
//      notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//    * Neither the name of the copyright holder nor the
//      names of its contributors may be used to endorse or promote products
//      derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
//DISCLAIMED. IN NO EVENT SHALL UGO VARETTO BE LIABLE FOR ANY
//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////////

#ifdef max
#undef max
#endif

#include <limits>

#include <QtWebKit/QWebElement>
#include <QtWebKit/QWebElementCollection>
#include <QString>
#include <QVariant>
#include <QVariantMap>
#include <QList>
#include <QStringList>

#include "LocoObject.h"
#include "LocoContext.h"

namespace loco {

class WebElement : public Object {
    Q_OBJECT
public:
    WebElement( const QWebElement& we ) : we_( we ) {}
    QWebElement& qWebElement() { return we_; }
    const QWebElement& qWebElement() const { return we_; }
public slots:
    QString styleProperty( const QString& name ) const {
        return we_.styleProperty( name, QWebElement::ComputedStyle );
    }
    QVariant findFirstElement( const QString& selectorQuery ) {
           QWebElement we = we_.findFirst( selectorQuery );
           if( we.isNull() ) return QVariant();
           return GetContext()->AddObjToJSContext( new WebElement( we ) ) ;
    }
    QList< QVariant > forEachElement( const QString& selectorQuery,
                                      const QString& cond,
                                      int maxNum = std::numeric_limits< int >::max() ) {
        QWebElementCollection wec = we_.findAll( selectorQuery );
        if( wec.count() < 1 ) return QList< QVariant >();
        QList< QVariant > we;
        int n = 0;
        for( QWebElementCollection::iterator i = wec.begin();
             i != wec.end() && n < maxNum; ++i, ++n ) {
              if( ( *i ).evaluateJavaScript( cond ).toBool() ) {
                     we.push_back( GetContext()->AddObjToJSContext( new WebElement( *i ) ) );
            }
        }
        return we;
    }
    QList< QVariant > findElements( const QString& selectorQuery ) const {
           QWebElementCollection wec = we_.findAll( selectorQuery );
           if( wec.count() < 1 ) return QList< QVariant >();
           QList< QVariant > we;
           for( QWebElementCollection::const_iterator i = wec.constBegin();
               i != wec.constEnd(); ++i ) {
               we.push_back( GetContext()->AddObjToJSContext( new WebElement( *i ) ) );
           }
           return we;
    }
    void setPlainText( const QString& text ) { we_.setPlainText( text ); }
    QString toPlainText() const { return we_.toPlainText(); }
    void setAttribute( const QString& name, const QString& value ) {
        we_.setAttribute( name, value );
    }
    void setAttributeNS( const QString& namespaceUri, const QString& name, const QString& value ) {
        we_.setAttributeNS( namespaceUri, name, value );
    }
    QString attribute( const QString& name, const QString& defaultValue = QString() ) const {
        return we_.attribute( name, defaultValue );
    }
    QString attributeNS( const QString& namespaceUri, const QString& name, const QString& defaultValue = QString() ) const {
        return we_.attributeNS( namespaceUri, name, defaultValue );
    }
    bool hasAttribute( const QString& name ) const {
        return we_.hasAttribute( name );
    }
    bool hasAttributeNS(const QString& namespaceUri, const QString& name) const {
        return we_.hasAttributeNS( namespaceUri, name );
    }
    void removeAttribute( const QString& name ) { we_.removeAttribute( name ); }
    void removeAttributeNS( const QString& namespaceUri, const QString& name ) {
        we_.removeAttributeNS( namespaceUri, name );
    }
    bool hasAttributes() const { return we_.hasAttributes(); }
    QStringList attributeNames(const QString& namespaceUri = QString()) const {
        return we_.attributeNames( namespaceUri );
    }
    QStringList classes() const { return we_.classes(); }
    bool hasClass( const QString& name ) const { return we_.hasClass( name ); }
    void addClass( const QString& name ) { we_.addClass( name ); }
    void removeClass( const QString& name ) { we_.removeClass( name ); }
    void toggleClass( const QString& name ) { we_.toggleClass( name ); }
    bool hasFocus() const { return we_.hasFocus(); }
    void setFocus() { we_.setFocus(); }
    QVariantMap geometry() const {
        const QRect r = we_.geometry();
        QVariantMap m;
        m[ "x" ] = r.x();
        m[ "y" ] = r.y();
        m[ "width" ] = r.width();
        m[ "height" ] = r.height();
        return m;
    }
    QString tagName() const { return we_.tagName(); }
    QString prefix() const { return we_.prefix(); }
    QString localName() const { return we_.localName(); }
    QString namespaceUri() const { return we_.namespaceUri(); }
    QVariant parent() {
        return GetContext()->AddObjToJSContext( new WebElement( we_.parent() ) );
    }
    QVariant firstChild() {
        return GetContext()->AddObjToJSContext( new WebElement( we_.firstChild() ) );
    }
    QVariant lastChild() {
        return GetContext()->AddObjToJSContext( new WebElement( we_.lastChild() ) );
    }
    QVariant nextSibling() {
        return GetContext()->AddObjToJSContext( new WebElement( we_.nextSibling() ) );
    }
    QVariant previousSibling() {
        return GetContext()->AddObjToJSContext( new WebElement( we_.previousSibling() ) );
    }
    QVariant document() {
        return GetContext()->AddObjToJSContext( new WebElement( we_.document() ) );
    }
    QWebFrame *webFrame() const { return we_.webFrame(); }
    void appendInside( const QString& markup ) { we_.appendInside( markup ); }
    void appendInside( const WebElement& element ) { we_.appendInside( element.qWebElement() ); }
    void prependInside( const QString& markup ) { we_.prependInside( markup ); }
    void prependInside( const WebElement& element ) { we_.prependInside( element.qWebElement() ); }
    void appendOutside( const QString& markup ) { we_.appendOutside( markup ); }
    void appendOutside( const WebElement& element ) { we_.appendInside( element.qWebElement() ); }
    void prependOutside( const QString& markup ) { we_.prependOutside( markup ); }
    void prependOutside( const WebElement& element ) { we_.prependOutside( element.qWebElement() ); }
    void encloseContentsWith( const WebElement& element ) {
        we_.encloseContentsWith( element.qWebElement() );
    }
    void encloseContentsWith( const QString& markup ) {
        we_.encloseContentsWith( markup );
    }
    void encloseWith( const QString& markup ) { we_.encloseWith( markup ); }
    void encloseWith( const WebElement& element ) {
        we_.encloseWith( element.qWebElement() );
    }
    void replace( const QString& markup ) { we_.replace( markup ); }
    void replace( const WebElement& element ) {
           we_.replace( element.qWebElement() );
    }
    QVariant clone() {
        return GetContext()->AddObjToJSContext( new WebElement( we_.clone() ) );
    }
    //QWebElement& takeFromDocument();
    void removeFromDocument() { we_.removeFromDocument(); }
    void removeAllChildren() { we_.removeAllChildren(); }
    QVariant eval( const QString& scriptSource ) {
        return we_.evaluateJavaScript( scriptSource );
    }
private:
    QWebElement we_;
};

}


This is my video to introduce visitors to Tekk's Tavern. It will be shown as the intro video for people visiting my channel that are not yet subscribed. Please feel free to browse my channel and videos and become one of the gang here at the Tavern. We will save you a spot at the bar and keep your tab up and running.
Thanks for visiting and look forward to having you back soon!
Just a small series showing some tips and early game concepts on playing CK2. This is not meant to be a complete and comprehensive video series but more of a beginner basics to help get people not familiar with the series or Paradox strategy games in general.


Hi! My name is Eric Crooks. I'm a designer and developer living in Raleigh, North Carolina–currently working as a software engineer for Cisco.
I'm mostly self-taught, but I do have a BS in Computer Information Systems and CoA in Graphic Communications. Both of these credentials make me scrutinize pixels and the inner workings of web frameworks.
I used to "jump from perfectly good airplanes" (I miss jumping from Sherpas), occasionally do some woodwork, and love tinkering with TSI engines.


You are given two integers $$$n$$$ and $$$k$$$.

You should create an array of $$$n$$$ positive integers $$$a_1, a_2, \dots, a_n$$$ such that the sum $$$(a_1 + a_2 + \dots + a_n)$$$ is divisible by $$$k$$$ and maximum element in $$$a$$$ is minimum possible.

What is the minimum possible maximum element in $$$a$$$?


Given an integer $$$n$$$, find an integer $$$x$$$ such that:

- $$$2 \leq x \leq n$$$.
- The sum of multiples of $$$x$$$ that are less than or equal to $$$n$$$ is maximized. Formally, $$$x + 2x + 3x + \dots + kx$$$ where $$$kx \leq n$$$ is maximized over all possible values of $$$x$$$.


Dear NEST Users,
As discussed a long time ago (see towards the end of the discussion in
), the hh_cond_exp_traub model included
in NEST is far from the model by Traub and Miles (1991) which inspired it. The model in
NEST was implemented as part of the work on the Brette et al (2007) review paper.
I am considering to create a pull request that will
1. rename the models to hh_brette_2007* in keeping with NEST naming guidelines for
2. change the threshold parameter V_T to be the actual threshold for spike emission
(currently the criterium is V_m >= V_T + 30
and falling V_m)
I was therefore wondering if anyone of you
1. uses the hh_cond_* models at all
2. would object to those changes?
Depending on whether the models are being used or not, I'd either implement the
renaming via deprecation or directly.
Prof. Dr. Hans Ekkehard Plesser
Head, Department of Data Science
Faculty of Science and Technology
Norwegian University of Life Sciences
PO Box 5003, 1432 Aas, Norway
Phone +47 6723 1560


I imagine their plans eventually include moving into home automation, most companies do these days.
That being said, IFTTT integration is available with version 2. (and I believe the developers reported before they will try to bring similar functionality via firmware updates to version 1) I believe Alexa support as well for asking to view the video on the active feed is my guess. If Google Home cleans up their “watch this on that” commands perhaps it would work well that but I don’t know what other features it would provide.
What do you mean to turn it on remotely?
Also, a quick toggle for notifications would be nice but could also be solved by geo-fencing in Most cases. I don’t know where you’d place that button that isn’t about equivalent of opening the app to turn them off.


I was recently working on a project in nanoc and installed
bundler so I could use
guard to watch the project directory.
Now when I run
nanoc view the webserver doesn't start up displaying the following error instead:
$ nanoc view Could not find the required 'adsf' gem, which is necessary for the view command.
I read in a google group that there has been some sort of a typo in which the gem packages
asdf have been confused. I tried installing both of them with
sudo gem install but I when I run the command I still get the same error message.


can I use a plain old 56k model built into my laptop with a adsl microfilter pluging into the telephone jack. The adsl runs to the adsl socket and I connect my modem to the phone socket. Can they run in parallel?
DSL works by multplexing the DSL signal and the voice signal on the same line, with the filters preventing the DSL signal from getting to phone equipment and preventing interference from the phone equipment within the DSL bandwidth. Since a 56k modem uses the voice bandwidth, both can coexist.


Lakhesh loves to make movies, so Nephren helps her run a cinema. We may call it No. 68 Cinema.

However, one day, the No. 68 Cinema runs out of changes (they don't have 50-yuan notes currently), but Nephren still wants to start their business. (Assume that yuan is a kind of currency in Regulu Ere.)

There are three types of customers: some of them bring exactly a 50-yuan note; some of them bring a 100-yuan note and Nephren needs to give a 50-yuan note back to him/her; some of them bring VIP cards so that they don't need to pay for the ticket.

Now n customers are waiting outside in queue. Nephren wants to know how many possible queues are there that they are able to run smoothly (i.e. every customer can receive his/her change), and that the number of 50-yuan notes they have after selling tickets to all these customers is between l and r, inclusive. Two queues are considered different if there exists a customer whose type is different in two queues. As the number can be large, please output the answer modulo p.


You could first define an xml layout for example
on your php server you have a page called mypage.php
$x = ... you assign a value to x ..;
echo "<result><x>" .$x."</x></result>";
your android app makes a call to http://domain-name/mypage.php
and gets as result "<result><x>5</x></result>"
parse the result and you have the value of x in your app
or if your php page is generating HTML (ie a page which is normally displayed via a browser) you can do the same but then you'll have the parse the HTML and search for the specific values you're looking for


You are given a weighted tree with $$$n$$$ vertices. Recall that a tree is a connected graph without any cycles. A weighted tree is a tree in which each edge has a certain weight. The tree is undirected, it doesn't have a root.

Since trees bore you, you decided to challenge yourself and play a game on the given tree.

In a move, you can travel from a node to one of its neighbors (another node it has a direct edge with).

You start with a variable $$$x$$$ which is initially equal to $$$0$$$. When you pass through edge $$$i$$$, $$$x$$$ changes its value to $$$x ~\mathsf{XOR}~ w_i$$$ (where $$$w_i$$$ is the weight of the $$$i$$$-th edge).

Your task is to go from vertex $$$a$$$ to vertex $$$b$$$, but you are allowed to enter node $$$b$$$ if and only if after traveling to it, the value of $$$x$$$ will become $$$0$$$. In other words, you can travel to node $$$b$$$ only by using an edge $$$i$$$ such that $$$x ~\mathsf{XOR}~ w_i = 0$$$. Once you enter node $$$b$$$ the game ends and you win.

Additionally, you can teleport at most once at any point in time to any vertex except vertex $$$b$$$. You can teleport from any vertex, even from $$$a$$$.

Answer with "YES" if you can reach vertex $$$b$$$ from $$$a$$$, and "NO" otherwise.

Note that $$$\mathsf{XOR}$$$ represents the bitwise XOR operation.


/*******************************************************************
*
* CAUTION: This file is automatically generated by HSM.
* Version:
* DO NOT EDIT.
*
*  v (64-bit)
SW Build (by ) on
Copyright 1986-2014 Xilinx, Inc. All Rights Reserved.
*
* Description: Exception Handling Header for MicroBlaze Processor
*
*******************************************************************/


Dear Octopi fans!
I am using Octopi since a couple of weeks on an Raspberry PI4 with 4Gb and i am really happy with.
There is only one thing i am a little bit frustated:
Warts form on the surface of the components.
See the pictures here on Amazon photos:
In an other forum they told me to ask you here, because they think the warts come from Octopi or the Raspberry, due to the fact that i do not have them, when i am printing from the SD card plugged into my Ender 5 Plus.
Do you have any tipps for me to reduce / solve this issue printing with Octopi?
Many thanks in advance!
Your printer probably stutters sometimes but we need the serial log to identify the problem.
Enable serial logging and upload a systeminfo bundle.
Also please fill out the form. It makes it much easier to help you
Then we need to know at which speeds your were printing when that happened (wall speeds (outer wall in particular)).
What is the problem?
What did you already try to solve it?
Have you tried running in safe mode?
Did running in safe mode solve the problem?
You can download this in OctoPrint's System Information dialog ... no bundle, no support!)
Additional information about your setup
OctoPrint version, OctoPi version, printer, firmware, browser, operating system, ... as much data as possible


#import <LegacyComponents/TGModernGalleryItemView.h>
#import "TGModernGalleryImageItemImageView.h"

@interface TGMediaPickerGalleryGifItemView : TGModernGalleryItemView

@property (nonatomic, strong) TGModernGalleryImageItemImageView *imageView;

@end


One day, Vlad became curious about who he can have a conversation with on the escalator in the subway. There are a total of $$$n$$$ passengers. The escalator has a total of $$$m$$$ steps, all steps indexed from $$$1$$$ to $$$m$$$ and $$$i$$$-th step has height $$$i \cdot k$$$.

Vlad's height is $$$H$$$ centimeters. Two people with heights $$$a$$$ and $$$b$$$ can have a conversation on the escalator if they are standing on different steps and the height difference between them is equal to the height difference between the steps.

For example, if two people have heights $$$170$$$ and $$$180$$$ centimeters, and $$$m = 10, k = 5$$$, then they can stand on steps numbered $$$7$$$ and $$$5$$$, where the height difference between the steps is equal to the height difference between the two people: $$$k \cdot 2 = 5 \cdot 2 = 10 = 180 - 170$$$. There are other possible ways.

Given an array $$$h$$$ of size $$$n$$$, where $$$h_i$$$ represents the height of the $$$i$$$-th person. Vlad is interested in how many people he can have a conversation with on the escalator individually.

For example, if $$$n = 5, m = 3, k = 3, H = 11$$$, and $$$h = [5, 4, 14, 18, 2]$$$, Vlad can have a conversation with the person with height $$$5$$$ (Vlad will stand on step $$$1$$$, and the other person will stand on step $$$3$$$) and with the person with height $$$14$$$ (for example, Vlad can stand on step $$$3$$$, and the other person will stand on step $$$2$$$). Vlad cannot have a conversation with the person with height $$$2$$$ because even if they stand on the extreme steps of the escalator, the height difference between them will be $$$6$$$, while their height difference is $$$9$$$. Vlad cannot have a conversation with the rest of the people on the escalator, so the answer for this example is $$$2$$$.


Alina has a bracket sequence $$$s$$$ of length $$$2n$$$, consisting of $$$n$$$ opening brackets '(' and $$$n$$$ closing brackets ')'. As she likes balance, she wants to turn this bracket sequence into a balanced bracket sequence.

In one operation, she can reverse any substring of $$$s$$$.

What's the smallest number of operations that she needs to turn $$$s$$$ into a balanced bracket sequence? It can be shown that it's always possible in at most $$$n$$$ operations.

As a reminder, a sequence of brackets is called balanced if one can turn it into a valid math expression by adding characters + and 1. For example, sequences (())(), (), and (()(())) are balanced, while )(, ((), and (()))( are not.


While looking at the kitchen fridge, the little boy Tyler noticed magnets with symbols, that can be aligned into a string $$$s$$$.

Tyler likes strings, and especially those that are lexicographically smaller than another string, $$$t$$$. After playing with magnets on the fridge, he is wondering, how many distinct strings can be composed out of letters of string $$$s$$$ by rearranging them, so that the resulting string is lexicographically smaller than the string $$$t$$$? Tyler is too young, so he can't answer this question. The alphabet Tyler uses is very large, so for your convenience he has already replaced the same letters in $$$s$$$ and $$$t$$$ to the same integers, keeping that different letters have been replaced to different integers.

We call a string $$$x$$$ lexicographically smaller than a string $$$y$$$ if one of the followings conditions is fulfilled:

- There exists such position of symbol $$$m$$$ that is presented in both strings, so that before $$$m$$$-th symbol the strings are equal, and the $$$m$$$-th symbol of string $$$x$$$ is smaller than $$$m$$$-th symbol of string $$$y$$$.
- String $$$x$$$ is the prefix of string $$$y$$$ and $$$x \neq y$$$.

Because the answer can be too large, print it modulo $$$998\,244\,353$$$.


You are given an array $$$a$$$ of length $$$2n$$$. Consider a partition of array $$$a$$$ into two subsequences $$$p$$$ and $$$q$$$ of length $$$n$$$ each (each element of array $$$a$$$ should be in exactly one subsequence: either in $$$p$$$ or in $$$q$$$).

Let's sort $$$p$$$ in non-decreasing order, and $$$q$$$ in non-increasing order, we can denote the sorted versions by $$$x$$$ and $$$y$$$, respectively. Then the cost of a partition is defined as $$$f(p, q) = \sum_{i = 1}^n |x_i - y_i|$$$.

Find the sum of $$$f(p, q)$$$ over all correct partitions of array $$$a$$$. Since the answer might be too big, print its remainder modulo $$$998244353$$$.


Finished her homework, Nastya decided to play computer games. Passing levels one by one, Nastya eventually faced a problem. Her mission is to leave a room, where a lot of monsters live, as quickly as possible.

There are $$$n$$$ manholes in the room which are situated on one line, but, unfortunately, all the manholes are closed, and there is one stone on every manhole. There is exactly one coin under every manhole, and to win the game Nastya should pick all the coins. Initially Nastya stands near the $$$k$$$-th manhole from the left. She is thinking what to do.

In one turn, Nastya can do one of the following:

- if there is at least one stone on the manhole Nastya stands near, throw exactly one stone from it onto any other manhole (yes, Nastya is strong).
- go to a neighboring manhole;
- if there are no stones on the manhole Nastya stays near, she can open it and pick the coin from it. After it she must close the manhole immediately (it doesn't require additional moves).

The figure shows the intermediate state of the game. At the current position Nastya can throw the stone to any other manhole or move left or right to the neighboring manholes. If she were near the leftmost manhole, she could open it (since there are no stones on it).

Nastya can leave the room when she picks all the coins. Monsters are everywhere, so you need to compute the minimum number of moves Nastya has to make to pick all the coins.

Note one time more that Nastya can open a manhole only when there are no stones onto it.


Most of this document is fine, but I have identified a number of problems with
scenarios, plus a few nits in the front of the document.
Scenarios which are missing (other than ones mentioned in my discussion of a section):
print request from windows with no attributes, the Printer may default attributes
except for production attributes which are embedded in the document data.
print request from Unix with no attributes, the Printer may default all attributes
including production attributes.
print request from some future system with attributes. This scenario seems to
be covered but doesn't deal with Printers which may not be able to
handle explicit production attributes.
The first two cases should at least be covered in the context where a Printer
sets defaults for unspecified attributes.
There are also issue with regard to whether an attribute expresses a requirement
or "best-effort". Perhaps there should be a scenario discussing this.
Section 2.1.1 Is "inside the firewall" an appropriate search criteria?
Section 220.127.116.11. The discussion about creating a queue on UNIX hosts is not right.
Several sentences in this area should be deleted.
Section 2.1.4, Paragraph 2. I would expect that a printer would always be
able to determine the format. Thus, that requirement should not be in a
sentence with an 'or'.
Section 2.1.4, Paragraph 3. The model document on line 335 of V1.5 specifies
what happens when a job requests and attribute or attribute value that a
printer does not support. Perhaps those details should be in the requirements
Section 2.1.4, last line. What is meant by "job default" as an example of
parameters to job print request.
Section 2.1.6. I believe that it is misleading to use the phrase "altering
the status of a submitted print job" to mean "cancelling a job", especially because
there will eventually be an operation to alter some attributes of a submitted
job. Another problem I see with this terminology is that the jobStatus and
printerStatus groups of attributes cannot be directly changed by any human.
Section 2.2.2. Same comment as for 2.1.6. Also, the "reprioritize either assumes
that the operator can modify the job-priority attribute via some "set" operaion or
that there is some "promote-job" operation. Neither operation has been defined.
Section 2.3. The bullets which mention pre-print and post-print introduce concepts
that are too vague. I would replace both by something such as and put it at the
end of the bulleted list:
o create, change or customize other printer features.
Section 3, bottom of page 11: Is this list of combinations of case with firewalls
useful? I don't think it is.
Section 3, top of page 14: I do not agree with most of the bulleted responses, such as
got print job, started to print but failed. The print operation should
be viewed as an operation to transmit attributes and document data. The
operation should primarily report back that the job was sucessfully transmitted
or it wasn't. Any job/printer status reported is merely a helpful snapshot that may
be inaccurate a moment later. Thus, while a Print operation is in progress, however
long that might be. When the print operation completes, its response indicates
whether the job was completely received or failed to be received. In the latter
case, the job does not complete printing, though some may have printed, and it
would be good for the printer to indicate how much has printed. This operation
should not be terminated because of a printer jam.
Section 3.6: As stated before, I don't believe the Job Modification should include
cancelling. Even the mentioned hold and release operations, need not actually
modify a job. From the stand point of a user model, the hold operation may
just put the job in a holding tank until it is released.
Section 4.2: Perhaps this is where the mapping between ipp and lpd should exists
in order to make the IESG happy.
Section 4.3: I wonder if we will need proxy printers to make the protocol pass
Section 8.6, page 26: The model currently does not return the printer state,
but it does return the job-state-reasons which will contain the value
"printer-stopped" if the printer's state it stopped.
Section 8.8, page 28: There are two cases here. One is that print operation
in the client gets notice that its connection to the printer has been dropped
and the other is that it times out. Note also, that a variant of this scenario
is that the printer is powered off before the Print starts. This case raises
lots of potentially bad and unsolvable problems.
In the "get notice" case, the Printer is sufficiently alive that can get
information about the problem to the client before it closes the connection,
and the client can use this information return a reasonable status to the
caller of the print operation. This status would likely be that the job
In the "time out" case, the client cannot know why the time-out occurred,
e.g. network down, printer down, or printer too busy to respond. This case
is probably best handled by assuming that the client will continue transmitting
when the printer resumes responding.
The summary of my comments, is that the scenario is incomplete and represents
Section 8.9: There are certain assumption about security here that should not
be a requirement document with regard to the exchanges that take place.
Also there are certain assumptions in this scenario about what has to
be authenticated. I assume that the end-user is trying to get a certificate
of authenticy from the printer and that the printer is only authenticating
that the payment is OK. The printer does not need to know who the person is
for allowing later cancellation of the job.
Section 8.11: This stated scenario and accompanying example don't seem right.
The scenario talks about authentication and yet the data is encrypted.
From the statement of the problem, the client should send the data in
clear form and then also send some password/userid information. Depending
on the protocol and client knowledge, the password/userid might accompany
the print request or it might be separate. In HTTP, it would likely be separate.
I would expect for this case to see either basic password or digest password.
There is no need to get a secret key for all this.
I think that this scenario is attempting to cover the simple authentication
case that current printer systems handle. Currently it does not.
Section 8.12: This should just specify that a user submits authentication and
it is rejected.
Section 8.13: I think that we all agreed in the protocol meeting that the protocol
doesn't limit the length of jobs. Therefore the print request and response
look the same for a 1K and 1Gig job. What we did recognize, is that some clients
may want to get a job-identifier back before the entire job has been transmitted.
That implies a print request can be fragmented into start print request,
continue print request and end print request, but a client could send a 1K job
via this mechanism.
So, the question is, what is the requirement here? Given that a print request
can submit as large a job as we wish, why does a client need a job-id before
a job has been transmitted? What is the use of any intermediate results?
Do we really expect that failure of an intermediate means anything but the
job was aborted, the same as the whole print request failing at the same point?
Section 8.14: I think that this scenario is unrealistic. If the printer jams and
runs out of space for any more of the job, then the client should hang on
a write operation until the jam is cleared. If someone hits reset on the
printer, then I would expect the print request to end with a job aborted status.
Likewise, if some one kills the transmission from the client side, I would
expect the printer to abort the job.
If this scenario is changed to the RIP encountered a fatal error, then this
scenario is OK, but it doesn't need all the intermediate parts of the operation.
It is sufficient to say that the response came back before the printer received
all the job data.
Section 8.15: Scenario is OK, but the transmissions should be changed to a single
request and response.
Section 8.16: There should be a statement to the effect that the referenced file
must be publicly accessible, otherwise there are lots of security issues.
Section 8.17: There is no need for this scenario. At the protocol level, the
document is one long stream, and a program reads it buffer by buffer.
Section 8.18: This section should omit any reference to long jobs. It should just
be pull with errors.
Section 8.21: There is a missing scenario, namely where the client requests all
attributes of a group, not knowing what new printer specific attributes might
be in such a group.
Section 8.23: There needs to another scenario "get the status of jobs on printer X".
Some printers give all such jobs and others give only those owned by the
user. We can support "get the status of jobs on printer X" with no authentication,
but not "get my jobs". There are still issues of authentication with the first
case if some attribute values are accessible to a job owner only.
Section 8.27: There should be some mention of authentication here. A person
should not be able to cancel a job that is not his job.
Page 55: Is there any reason why the print request is broken into pieces?
Page 58: I think it is important to state that the fetching of printer attributes
would not be done by today's pc drivers. Rather this is how future systems
might do this.
Page 59: Again, get rid of the multiple parts of the print request to simplify
Section 8.30: As I said previously, I don't think that authentication is going on
in the sense of verifying the identity. Rather it is verifying the availabilty
of payment. For cancel job there are reasons to verify that the person cancelling
is the same as the person submitting the job.
Page 63: Again, get rid of the multiple parts of the print request to simplify


You are given a problemset consisting of $$$n$$$ problems. The difficulty of the $$$i$$$-th problem is $$$a_i$$$. It is guaranteed that all difficulties are distinct and are given in the increasing order.

You have to assemble the contest which consists of some problems of the given problemset. In other words, the contest you have to assemble should be a subset of problems (not necessary consecutive) of the given problemset. There is only one condition that should be satisfied: for each problem but the hardest one (the problem with the maximum difficulty) there should be a problem with the difficulty greater than the difficulty of this problem but not greater than twice the difficulty of this problem. In other words, let $$$a_{i_1}, a_{i_2}, \dots, a_{i_p}$$$ be the difficulties of the selected problems in increasing order. Then for each $$$j$$$ from $$$1$$$ to $$$p-1$$$ $$$a_{i_{j + 1}} \le a_{i_j} \cdot 2$$$ should hold. It means that the contest consisting of only one problem is always valid.

Among all contests satisfying the condition above you have to assemble one with the maximum number of problems. Your task is to find this number of problems.


Alice and Bob are playing a game on a sequence $$$a_1, a_2, \dots, a_n$$$ of length $$$n$$$. They move in turns and Alice moves first.

In the turn of each player, he or she should select an integer and remove it from the sequence. The game ends when there is no integer left in the sequence.

Alice wins if the sum of her selected integers is even; otherwise, Bob wins.

Your task is to determine who will win the game, if both players play optimally.